From 8473664ce4685cf307d0fdf054097e09fcd44e06 Mon Sep 17 00:00:00 2001 From: Youssef Date: Thu, 14 May 2026 23:48:06 +0100 Subject: [PATCH 01/36] update docs --- docs/ai-agents/guides/batch-calls.mdx | 66 +++ docs/ai-agents/guides/check-balance.mdx | 53 +++ docs/ai-agents/guides/index.mdx | 29 ++ docs/ai-agents/guides/pay-for-services.mdx | 90 ++++ docs/ai-agents/guides/send-tokens.mdx | 73 +++ docs/ai-agents/guides/sign-messages.mdx | 60 +++ docs/ai-agents/guides/swap-tokens.mdx | 57 +++ docs/ai-agents/guides/view-history.mdx | 64 +++ docs/ai-agents/index.mdx | 92 ++-- docs/ai-agents/payments.mdx | 35 ++ .../ai-agents/payments/accepting-payments.mdx | 146 ------ .../payments/pay-for-services-with-x402.mdx | 157 ------- docs/ai-agents/plugins/morpho.mdx | 184 ++++++++ docs/ai-agents/quickstart.mdx | 197 ++++++++ docs/ai-agents/quickstart/payments.mdx | 130 ------ docs/ai-agents/quickstart/trading.mdx | 102 ---- docs/ai-agents/setup/agent-registration.mdx | 188 -------- docs/ai-agents/setup/index.mdx | 178 +++++++ docs/ai-agents/setup/wallet-setup.mdx | 109 ----- docs/ai-agents/skills/index.mdx | 57 +-- .../skills/payments/cdp-payment-skills.mdx | 14 +- .../ai-agents/skills/payments/sponge-x402.mdx | 37 -- .../trading/alchemy-agentic-gateway.mdx | 47 -- docs/ai-agents/skills/trading/coingecko.mdx | 46 -- .../skills/trading/swap-execution.mdx | 50 -- docs/ai-agents/skills/wallets/bankr.mdx | 50 -- .../skills/wallets/cdp-agentic-wallet.mdx | 18 +- .../skills/wallets/sponge-wallet.mdx | 54 --- docs/ai-agents/trading/data-fetching.mdx | 190 -------- docs/ai-agents/trading/trade-execution.mdx | 115 ----- docs/docs.json | 113 +++-- docs/snippets/AcceptingPaymentsDemo.jsx | 126 ++--- docs/snippets/AgentPaymentDemo.jsx | 438 ++++++++---------- docs/snippets/AgentRegistrationDemo.jsx | 122 ++--- docs/snippets/DataFetchingDemo.jsx | 170 ++++--- docs/snippets/PaymentsQuickstartDemo.jsx | 68 +-- docs/snippets/TradeExecutionDemo.jsx | 131 ++---- docs/snippets/TradingQuickstartDemo.jsx | 125 ++--- docs/snippets/WalletSetupDemo.jsx | 226 ++++----- docs/snippets/x402PayDemo.jsx | 124 ++--- 40 files changed, 1879 insertions(+), 2452 deletions(-) create mode 100644 docs/ai-agents/guides/batch-calls.mdx create mode 100644 docs/ai-agents/guides/check-balance.mdx create mode 100644 docs/ai-agents/guides/index.mdx create mode 100644 docs/ai-agents/guides/pay-for-services.mdx create mode 100644 docs/ai-agents/guides/send-tokens.mdx create mode 100644 docs/ai-agents/guides/sign-messages.mdx create mode 100644 docs/ai-agents/guides/swap-tokens.mdx create mode 100644 docs/ai-agents/guides/view-history.mdx create mode 100644 docs/ai-agents/payments.mdx delete mode 100644 docs/ai-agents/payments/accepting-payments.mdx delete mode 100644 docs/ai-agents/payments/pay-for-services-with-x402.mdx create mode 100644 docs/ai-agents/plugins/morpho.mdx create mode 100644 docs/ai-agents/quickstart.mdx delete mode 100644 docs/ai-agents/quickstart/payments.mdx delete mode 100644 docs/ai-agents/quickstart/trading.mdx delete mode 100644 docs/ai-agents/setup/agent-registration.mdx create mode 100644 docs/ai-agents/setup/index.mdx delete mode 100644 docs/ai-agents/setup/wallet-setup.mdx delete mode 100644 docs/ai-agents/skills/payments/sponge-x402.mdx delete mode 100644 docs/ai-agents/skills/trading/alchemy-agentic-gateway.mdx delete mode 100644 docs/ai-agents/skills/trading/coingecko.mdx delete mode 100644 docs/ai-agents/skills/trading/swap-execution.mdx delete mode 100644 docs/ai-agents/skills/wallets/bankr.mdx delete mode 100644 docs/ai-agents/skills/wallets/sponge-wallet.mdx delete mode 100644 docs/ai-agents/trading/data-fetching.mdx delete mode 100644 docs/ai-agents/trading/trade-execution.mdx diff --git a/docs/ai-agents/guides/batch-calls.mdx b/docs/ai-agents/guides/batch-calls.mdx new file mode 100644 index 000000000..f74b05bff --- /dev/null +++ b/docs/ai-agents/guides/batch-calls.mdx @@ -0,0 +1,66 @@ +--- +title: "Execute Contract Calls" +description: "Batch multiple contract interactions into a single user approval using send_calls and the Base Account MCP" +keywords: ["send_calls MCP", "batch contract calls AI", "EIP-5792 AI", "DeFi AI agent", "Morpho AI Base", "batch transaction AI"] +--- + +import { AcceptingPaymentsDemo } from "/snippets/AcceptingPaymentsDemo.jsx" + + + +## What it does + +`send_calls` submits a batch of EIP-5792 contract calls to your Base Account in a single approval. Use it for DeFi interactions, multi-step operations, and NFT mints that go beyond simple send or swap. + +The most common use case: protocol plugins like [Morpho](/ai-agents/plugins/morpho) prepare a `calls` array (including token approvals and deposits), and you pass it directly to `send_calls` — everything executes atomically in one approval. + +## What you can ask + +With the [Morpho plugin](/ai-agents/plugins/morpho) installed: + +```text +Find the best USDC vault on Base and deposit 100 USDC +``` + +```text +Supply 1 ETH as collateral on Morpho and borrow 2000 USDC +``` + +```text +Repay all my Morpho debt +``` + +## How it works + + + + Protocol plugins like Morpho return a `calls` array and `chainId` from their `prepare_*` tools. The calls include any required token approvals and the protocol interaction itself. + + + Passes the `calls` array and hex `chainId` to the Base Account MCP. + + + Open the `keys.coinbase.com` link to review all calls in the batch before signing. + + + All calls in the batch execute atomically — if one fails, none go through. + + + +## Parameters + +| Parameter | Required | What it does | +|-----------|----------|-------------| +| `chainId` | Yes | Hex chain ID: `0x2105` for Base mainnet, `0x14a34` for Base Sepolia | +| `calls` | Yes | Array of `{ to, value?, data? }` objects | + +## Related guides + + + + Full Morpho orchestration pattern — query, prepare, execute. + + + Sign individual messages and typed data. + + diff --git a/docs/ai-agents/guides/check-balance.mdx b/docs/ai-agents/guides/check-balance.mdx new file mode 100644 index 000000000..a80b8088b --- /dev/null +++ b/docs/ai-agents/guides/check-balance.mdx @@ -0,0 +1,53 @@ +--- +title: "Check Balance & Portfolio" +description: "View your token balances, portfolio value, and wallet details using the Base Account MCP" +keywords: ["check balance AI", "get_portfolio MCP", "get_wallets MCP", "Base wallet balance AI assistant"] +--- + +import { DataFetchingDemo } from "/snippets/DataFetchingDemo.jsx" + + + +## What you can ask + +```text +Show me my wallets +``` + +```text +What's my USDC balance on Base? +``` + +```text +Show my full portfolio +``` + +```text +What's the balance of 0x1234...abcd? +``` + +## How it works + +**`get_wallets`** — lists all wallets in your wallet group (your Base Account plus any agent wallets). Shows which wallets are active in the current session (`inSession: true`). + +**`get_portfolio`** — returns portfolio value and per-asset breakdown. Works for any public address — not just your own. + +| Parameter | What it does | +|-----------|-------------| +| `address` | Address to query — defaults to your Base Account | +| `chain` | Filter by chain: `base` or `ethereum` | +| `query` | Filter by token name or symbol (e.g. "USDC") | +| `includePnl` | Include unrealized/realized P&L per asset | + +**`search_tokens`** — resolve a token symbol or name to its contract address and decimals. Useful before sending less common tokens. + +## Related guides + + + + Send ETH or any ERC-20 from your Base Account. + + + See past sends, swaps, and receives. + + diff --git a/docs/ai-agents/guides/index.mdx b/docs/ai-agents/guides/index.mdx new file mode 100644 index 000000000..05528311c --- /dev/null +++ b/docs/ai-agents/guides/index.mdx @@ -0,0 +1,29 @@ +--- +title: "Guides" +description: "Step-by-step guides for common things to do with your Base Account MCP" +keywords: ["Base Account MCP guides", "send tokens AI", "swap tokens AI", "check balance AI", "x402 payments AI"] +--- + + + + View your token balances, portfolio value, and wallet details. + + + Send ETH or any ERC-20 to an address, ENS name, or basename. + + + Swap between any two tokens via the Coinbase swap service. + + + Pay for API access per-request in USDC — no subscriptions, no API keys. + + + Browse past transactions and filter by asset or date range. + + + Sign EIP-712 typed data and plain messages for authentication. + + + Batch multiple contract interactions into a single user approval. + + diff --git a/docs/ai-agents/guides/pay-for-services.mdx b/docs/ai-agents/guides/pay-for-services.mdx new file mode 100644 index 000000000..6587f588c --- /dev/null +++ b/docs/ai-agents/guides/pay-for-services.mdx @@ -0,0 +1,90 @@ +--- +title: "Pay for Services (x402)" +description: "Pay for API access per-request in USDC using the x402 protocol — no subscriptions, no API keys required" +keywords: ["x402 payments AI", "pay for API AI", "pay-for-service skill", "x402 protocol Base", "USDC API payments AI agent"] +--- + +import { PaymentsQuickstartDemo } from "/snippets/PaymentsQuickstartDemo.jsx" + + + +## What is x402? + +x402 is a payment protocol built on HTTP status `402 Payment Required`. When your agent calls an x402-enabled API without paying, the server responds with `402` and payment terms (amount, token, network). Your agent pays in USDC and retries — the entire flow is automatic. + +No subscriptions. No API keys. No pre-existing relationship with the provider. + +## What you can ask + +```text +Find a weather API and get the forecast for New York +``` + +```text +Get the current ETH price from a paid data source +``` + +```text +Find APIs for sentiment analysis +``` + +```text +Set up a paid endpoint for my market data at $0.01 per request +``` + +## x402 with CDP Agentic Wallet + +x402 payments currently require the **CDP Agentic Wallet** skill. Install it once and your agent handles discovery, payment, and retries automatically. + +```bash Terminal +npx skills add coinbase/agentic-wallet-skills +``` + +Then authenticate: + +```text +Sign in to my wallet with your@email.com +``` + +The `pay-for-service` skill handles the full flow: discovers the API, pays in USDC, retries with the payment signature, and returns the data. + + +x402 support for the Base Account MCP is coming soon. Once available, no separate wallet skill will be needed — your Base Account will pay directly. + + +## How the x402 flow works + + + + A standard HTTP request to any x402-enabled endpoint. + + + The response includes payment terms: how much, which token, which network. + + + The CDP Agentic Wallet constructs and signs a payment in USDC on Base. + + + The original request is retried with the `X-Payment-Signature` header. The server verifies and returns the data. + + + +## Discover x402 services + +Browse the x402 Bazaar to find APIs that accept per-request USDC payments: + +```bash Terminal +npx awal@latest x402 bazaar search "price feed" +npx awal@latest x402 bazaar list --network base +``` + +## Reference + + + + Install the wallet skill needed for x402 payments today. + + + search-for-service, pay-for-service, and monetize-service skills. + + diff --git a/docs/ai-agents/guides/send-tokens.mdx b/docs/ai-agents/guides/send-tokens.mdx new file mode 100644 index 000000000..bddbe3f29 --- /dev/null +++ b/docs/ai-agents/guides/send-tokens.mdx @@ -0,0 +1,73 @@ +--- +title: "Send Tokens" +description: "Send ETH or any ERC-20 token to an address, ENS name, basename, or cb.id using the Base Account MCP" +keywords: ["send tokens AI", "send USDC AI assistant", "send ETH AI", "Base Account MCP send", "ENS basename send AI"] +--- + +import { TradeExecutionDemo } from "/snippets/TradeExecutionDemo.jsx" + + + +## What you can ask + +```text +Send 10 USDC to alice.base.eth +``` + +```text +Transfer 0.01 ETH to 0x1234...abcd +``` + +```text +Pay bob.eth 5 USDC +``` + +```text +Send 50 DEGEN to vitalik.eth +``` + +## How it works + +The `send` tool constructs a transaction from your Base Account and requires your approval at `keys.coinbase.com`. Nothing is sent until you confirm. + +| Parameter | Required | What it does | +|-----------|----------|-------------| +| `recipient` | Yes | Address, ENS name, basename (e.g. `alice.base.eth`), cb.id name, or username | +| `amount` | Yes | Human-readable decimal (e.g. `"10.5"`) | +| `asset` | Yes | Token symbol (`ETH`, `USDC`) or ERC-20 contract address | +| `chain` | Yes | `base` or `base-sepolia` | +| `decimals` | When using contract address | Required when `asset` is a contract address | + + +For common tokens like ETH and USDC, just use the symbol — no contract address needed. For less common tokens, your assistant will call `search_tokens` first to resolve the address and decimals automatically. + + +## Approval flow + +Every send requires a manual approval: + + + + The transaction is constructed but not yet broadcast. + + + Open the `keys.coinbase.com` link to review the recipient, amount, and fee. + + + Confirm the transaction in the approval UI. Nothing is sent without your explicit confirmation. + + + Your assistant polls `get_request_status` and reports success once the transaction is confirmed onchain. + + + +## Related guides + + + + Exchange one token for another. + + + Verify your balance before sending. + + diff --git a/docs/ai-agents/guides/sign-messages.mdx b/docs/ai-agents/guides/sign-messages.mdx new file mode 100644 index 000000000..6bac6d967 --- /dev/null +++ b/docs/ai-agents/guides/sign-messages.mdx @@ -0,0 +1,60 @@ +--- +title: "Sign Messages" +description: "Sign EIP-712 typed data and plain messages with your Base Account using the Base Account MCP" +keywords: ["sign message AI", "EIP-712 sign AI", "personal_sign AI", "Base Account MCP sign", "sign typed data AI assistant"] +--- + +import { X402PayDemo } from "/snippets/x402PayDemo.jsx" + + + +## What it does + +The `sign` tool requests a cryptographic signature from your Base Account. Like all write tools, it requires your approval at `keys.coinbase.com`. + +Two signature types are supported: + +| Type | Standard | Use case | +|------|----------|---------| +| `0x45` | personal_sign (EIP-191) | Simple text messages, SIWE auth challenges | +| `0x01` | EIP-712 typed data | Structured data, permit signatures, protocol auth | + +## What you can ask + +```text +Sign this message: "I agree to the terms of service" +``` + +```text +Sign in to this app using my Base Account +``` + +Signing is usually invoked by protocols or integrations, not directly prompted by users. Your assistant will handle the signing flow when a service requests it. + +## How it works + + + + Passes the message type and payload to the Base Account MCP. + + + Open `keys.coinbase.com` to review what you're signing — the message content is shown in full. + + + Confirm the signature in the approval UI. + + + Your assistant polls `get_request_status` to retrieve the completed signature, then passes it to the requesting service. + + + +## Related guides + + + + Batch multiple contract interactions into one approval. + + + Example of signing-in-the-flow with a DeFi protocol. + + diff --git a/docs/ai-agents/guides/swap-tokens.mdx b/docs/ai-agents/guides/swap-tokens.mdx new file mode 100644 index 000000000..afeb0e880 --- /dev/null +++ b/docs/ai-agents/guides/swap-tokens.mdx @@ -0,0 +1,57 @@ +--- +title: "Swap Tokens" +description: "Swap between any two tokens on Base via the Coinbase swap service using the Base Account MCP" +keywords: ["swap tokens AI", "token swap AI assistant", "USDC ETH swap AI", "Base Account MCP swap", "DeFi swap AI"] +--- + +import { TradingQuickstartDemo } from "/snippets/TradingQuickstartDemo.jsx" + + + +## What you can ask + +```text +Swap 100 USDC for ETH on Base +``` + +```text +Buy $50 of ETH with USDC +``` + +```text +Trade 0.01 ETH for USDC +``` + +```text +Convert all my USDC to ETH +``` + +## How it works + +The `swap` tool routes through the Coinbase swap service and requires your approval at `keys.coinbase.com`. Swaps are only supported on mainnet — not on testnets. + +| Parameter | Required | What it does | +|-----------|----------|-------------| +| `fromAsset` | Yes | Token to swap from — symbol (`USDC`) or contract address | +| `toAsset` | Yes | Token to swap to — symbol (`ETH`) or contract address | +| `amount` | Yes | Amount of `fromAsset` to swap (human-readable decimal) | +| `chain` | Yes | `base` — testnets are not supported | + + +Testnet swaps are not supported. If you need to test, use `send` on `base-sepolia` instead. + + +## Approval flow + +Same as sending — every swap requires approval at `keys.coinbase.com`. Your assistant will give you a link to review the swap details (input amount, expected output, price impact) before anything is signed. + +## Related guides + + + + Send tokens directly to another address. + + + Verify balances before swapping. + + diff --git a/docs/ai-agents/guides/view-history.mdx b/docs/ai-agents/guides/view-history.mdx new file mode 100644 index 000000000..f517f3539 --- /dev/null +++ b/docs/ai-agents/guides/view-history.mdx @@ -0,0 +1,64 @@ +--- +title: "View Transaction History" +description: "Browse past transactions, filter by asset, and paginate through your onchain history using the Base Account MCP" +keywords: ["transaction history AI", "get_transaction_history MCP", "Base wallet history AI", "onchain history AI assistant"] +--- + +import { AgentRegistrationDemo } from "/snippets/AgentRegistrationDemo.jsx" + + + +## What you can ask + +```text +Show my recent transactions on Base +``` + +```text +Show my last 10 USDC transactions +``` + +```text +What did I send last week? +``` + +```text +Check the transaction history for 0x1234...abcd +``` + +## How it works + +`get_transaction_history` returns transactions in reverse chronological order (newest first) for any public wallet address. + +| Parameter | What it does | +|-----------|-------------| +| `address` | Address to query — defaults to your Base Account | +| `chain` | `base` or `ethereum` — defaults to `base` | +| `asset` | Filter to a specific token (e.g. `USDC`, `ETH`) | +| `limit` | Number of transactions per page (1–200, default 50) | +| `cursor` | Pagination cursor from the previous response's `nextCursor` | + + +Date range filtering is not supported — paginate through results to find transactions from a specific period. + + +## Pagination + +When `hasMore` is `true` in the response, more transactions exist. Ask your assistant to load more: + +```text +Show me the next page of transactions +``` + +Your assistant will use the `nextCursor` value from the previous response automatically. + +## Related guides + + + + View current balances alongside history. + + + Send tokens from your Base Account. + + diff --git a/docs/ai-agents/index.mdx b/docs/ai-agents/index.mdx index 9e9d47dfa..e168fc504 100644 --- a/docs/ai-agents/index.mdx +++ b/docs/ai-agents/index.mdx @@ -1,65 +1,69 @@ --- title: "AI Agents on Base" -description: "Build AI agents that trade, earn, and transact autonomously on Base" -keywords: ["AI agents Base", "x402 protocol", "onchain agents", "Base L2", "Build with AI", "OpenClaw", "trading agent", "payment agent"] +description: "Give your AI assistant a wallet. The Base Account MCP connects any AI to your Base Account — check balances, send funds, swap tokens, and sign messages." +keywords: ["Base Account MCP", "AI agent wallet", "mcp.base.org", "Base MCP", "AI assistant wallet", "onchain AI"] --- import { AgentPaymentDemo } from "/snippets/AgentPaymentDemo.jsx" -Base gives your AI agent the tools to operate as an independent economic actor: a wallet to hold and spend funds, identity standards so other agents and services can trust it, and payment protocols for services and commerce. +The Base Account MCP gives your AI assistant direct access to your [Base Account](https://base.org/account) — a smart wallet on Base. Connect once and your assistant can check balances, send funds, swap tokens, and sign messages. Every transaction requires your approval. - -## Mock Demo +## Demo -### High-level flow - -Here's how the agent you can build from these guides operates end-to-end — from wallet setup and identity registration to making authenticated, paid API requests using the [x402 protocol](https://www.x402.org). +## How it works ```mermaid sequenceDiagram - participant Agent - participant Wallet as Agent Wallet - participant Registry as Identity Registry - participant API as Paid API - participant Facilitator as x402 Facilitator - - Agent->>Wallet: Set up wallet (Bankr / CDP / Sponge) - Wallet-->>Agent: Address + signing capability - - Agent->>Registry: Register identity (ERC-8004 + Basename) - Registry-->>Agent: Agent ID published onchain - - Agent->>API: HTTP request - API-->>Agent: 402 Payment Required - Note over API,Agent: PAYMENT-REQUIRED header includes amount, token, and network - Agent->>Wallet: Sign payment payload - Wallet-->>Agent: Signed payment - Agent->>API: Retry with PAYMENT-SIGNATURE header - API->>Facilitator: Verify and settle payment - Facilitator-->>API: Payment confirmed - API-->>Agent: Response data + participant User + participant AI as AI Assistant + participant MCP as Base Account MCP + participant BA as Base Account + participant Approve as keys.coinbase.com + + User->>AI: "Send 10 USDC to alice.base.eth" + AI->>MCP: send(recipient, amount, asset, chain) + MCP->>BA: Construct transaction + BA-->>MCP: approvalUrl + requestId + MCP-->>AI: { approvalUrl, requestId } + AI-->>User: "Please approve: [link]" + User->>Approve: Opens link, approves + AI->>MCP: get_request_status(requestId) + MCP-->>AI: confirmed + AI-->>User: "Done — 10 USDC sent" ``` -## How this section is organized - -The AI agents section covers the full stack for building an autonomous onchain agent: +## What you can do -- **[Quickstarts](/ai-agents/quickstart/payments)** — End-to-end walkthroughs to get a working agent running in minutes. Start here if you're new. -- **[Setup](/ai-agents/setup/wallet-setup)** — Give your agent a wallet and a registered onchain identity. Wallets let it hold funds and authorize transactions; registration lets other agents and services verify who they're dealing with. -- **[Payments](/ai-agents/payments/pay-for-services-with-x402)** — Use x402 to pay for API access per-request in stablecoins, with no subscriptions or API keys required. Or gate your own endpoints to charge other agents. -- **[Trading](/ai-agents/trading/data-fetching)** — Fetch live market data and execute token swaps on Base. -- **[Skills](/ai-agents/skills)** — Installable knowledge packs that give your AI coding assistant deep context on Base APIs, tooling, and migration paths. + + + View your portfolio, token balances, and transaction history across any address on Base. + + + Send ETH or any ERC-20 token to addresses, ENS names, basenames, and cb.id names. + + + Swap between any tokens via the Coinbase swap service directly from your assistant. + + + Sign EIP-712 typed data and personal messages for authentication and protocol interactions. + + -## Choose your path +## Get started - - Build an agent that pays for API access with stablecoins and charges other agents for your services. Get running in under 10 minutes. + + Connect mcp.base.org to your AI assistant in under 2 minutes. - - - Build an agent that fetches live market data and executes token swaps automatically on Base. + + Step-by-step guides for sending, swapping, checking balance, and more. + + + Extend with protocol plugins like Morpho for lending and vaults. + + + Install the base-mcp skill to give your coding assistant deep context on MCP tools. - \ No newline at end of file + diff --git a/docs/ai-agents/payments.mdx b/docs/ai-agents/payments.mdx new file mode 100644 index 000000000..31d3d68ad --- /dev/null +++ b/docs/ai-agents/payments.mdx @@ -0,0 +1,35 @@ +--- +title: "Payments (x402)" +description: "x402 payment protocol support for AI agents on Base" +keywords: ["x402 agent payments", "Base Account MCP x402", "CDP agentic wallet x402", "agent payments Base"] +--- + +import { PaymentsQuickstartDemo } from "/snippets/PaymentsQuickstartDemo.jsx" + + + +## x402 and the Base Account MCP + +The Base Account MCP supports sending and swapping tokens directly. **x402 payment protocol** — which lets agents pay for API access per-request in stablecoins — is not yet supported through the Base Account MCP. + + +x402 support for the Base Account MCP is coming soon. + + +## For x402 payments today: CDP Agentic Wallet + +If you need your agent to make or accept x402 payments right now, use the [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/welcome): + +```bash Terminal +npx skills add coinbase/agentic-wallet-skills +``` + +The CDP Agentic Wallet skill bundle includes `pay-for-service`, `search-for-service`, and `monetize-service` — the full x402 client and server stack. + + + Set up x402 payments with the CDP Agentic Wallet. + + +See also: +- [CDP Agentic Wallet skill →](/ai-agents/skills/wallets/cdp-agentic-wallet) +- [CDP payment skills →](/ai-agents/skills/payments/cdp-payment-skills) diff --git a/docs/ai-agents/payments/accepting-payments.mdx b/docs/ai-agents/payments/accepting-payments.mdx deleted file mode 100644 index 8dcea8224..000000000 --- a/docs/ai-agents/payments/accepting-payments.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: "Accepting Payments (x402)" -description: "Gate your agent's endpoints with x402 to charge other agents per request" -keywords: ["x402 server", "accept agent payments", "monetize API agent", "x402-express", "monetize-service skill", "OpenClaw x402 server"] ---- - -import { AcceptingPaymentsDemo } from "/snippets/AcceptingPaymentsDemo.jsx" - -You can build agent services that charge other agents for access using x402. When a client calls your endpoint without paying, you return `402` with payment requirements. Once the client pays, the facilitator verifies the payment and your server delivers the response. - -## Mock Demo - - - -## Option 1 — OpenClaw monetize-service skill (simplest) - -With the CDP Agentic Wallet skills installed, expose a paid endpoint with a single prompt: - -```bash Terminal -npx skills add coinbase/agentic-wallet-skills -``` - -Then ask your agent: - -```text -Set up a paid endpoint for my market data at $0.01 per request -``` - -The `monetize-service` skill configures the x402 gating and deploys the endpoint. No server code required. - -[CDP Agentic Wallet skills →](https://docs.cdp.coinbase.com/agentic-wallet/skills) - -## Option 2 — Sponge Wallet payment links - -Create a reusable x402 payment link that other agents pay before accessing your service: - -```bash Terminal -curl -X POST "https://api.wallet.paysponge.com/api/payment-links" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" \ - -H "Content-Type: application/json" \ - -d '{ - "amount": "0.01", - "description": "Access to my market data API" - }' -``` - -Share the returned payment link URL with clients. Check payment status: - -```bash Terminal -curl "https://api.wallet.paysponge.com/api/payment-links/{paymentLinkId}" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" -``` - -[Sponge Wallet docs →](https://wallet.paysponge.com/skill.md) - -## Option 3 — Custom server with x402-express - -Use the `x402-express` package to add payment gating to any Express endpoint: - -```bash Terminal -npm install x402-express express -``` - -```typescript TypeScript -import express from "express"; -import { paymentMiddleware } from "x402-express"; - -const app = express(); - -app.use( - paymentMiddleware( - "0xYourAgentWalletAddress", - { - "/api/data": { - price: "$0.01", - network: "base-sepolia", - }, - } - ) -); - -app.get("/api/data", (req, res) => { - res.json({ data: "premium content" }); -}); - -app.listen(3000); -``` - -The middleware returns `402` to unpaid callers. The CDP facilitator handles verification and onchain settlement. - -[x402 seller quickstart →](https://docs.cdp.coinbase.com/x402/docs/client-server-model) - -## Configuring facilitators - -A facilitator is the off-chain service that verifies payment payloads and settles payments onchain. Two options: - -| Facilitator | When to use | -|-------------|-------------| -| **CDP facilitator** (default) | Production — requires CDP API key, supports Base and Solana | -| **Public testnet facilitator** | Development — no API key, Base Sepolia only | - -The public testnet facilitator endpoint is `https://www.x402.org/facilitator`. Switch to the CDP facilitator for mainnet. See the [x402 client-server model](https://docs.cdp.coinbase.com/x402/docs/client-server-model) for full endpoint details. - -## Pricing and payment terms - -- Set prices in USD (e.g., `"$0.01"`) — the middleware converts to the appropriate token amount -- Payments settle in USDC on Base by default -- There is no minimum payment — even fractions of a cent are supported -- Your wallet receives payment directly — no platform fee from the protocol - -## Make your endpoint discoverable - -Host a `SKILL.md` file at `/.well-known/SKILL.md` describing your endpoint's inputs, outputs, pricing, and authentication requirements. Agents discover your service by checking this path. - -```markdown SKILL.md template -# Your Agent Service - -## Description -What your service does, in plain language. - -## Endpoints - -### GET /api/data -- **Description:** Returns premium market data -- **Payment:** $0.01 per request via x402 (Base, USDC) -- **Output:** JSON with current prices and volume - -## Authentication -x402 payment required. No API key needed. -``` - -Register your service in the ERC-8004 registry so agents can discover it by category — see [agent registration](/ai-agents/setup/agent-registration). - -## Related - - - - How x402 works from the client side. - - - - Facilitator endpoints and protocol addresses. - - diff --git a/docs/ai-agents/payments/pay-for-services-with-x402.mdx b/docs/ai-agents/payments/pay-for-services-with-x402.mdx deleted file mode 100644 index 6153baaab..000000000 --- a/docs/ai-agents/payments/pay-for-services-with-x402.mdx +++ /dev/null @@ -1,157 +0,0 @@ ---- -title: "Pay for APIs & Services (x402)" -description: "How x402 works, how your agent makes payments, and which networks and tokens are supported" -keywords: ["x402 protocol", "autonomous agent payments", "machine payments protocol", "programmatic payments", "AI agent payments", "agentic payments", "HTTP 402 payment required", "x402 Base"] ---- - -import { X402PayDemo } from "/snippets/x402PayDemo.jsx" - -x402 is a payment protocol built on HTTP status code `402 Payment Required` — a code in the HTTP spec since the 1990s, finally put to use. It lets agents pay for API access with stablecoins per-request, with no subscriptions or API keys required. - -## Mock Demo - - - -## Payment flow - - - - Your agent sends a standard HTTP request to an API endpoint, just like any other API call. - - - - Instead of returning data, the server responds with a `402` status code and includes payment requirements in the `PAYMENT-REQUIRED` header: how much it costs, which token, and on which network. - - - - Your agent's wallet constructs a signed payment payload and resubmits the request with a `PAYMENT-SIGNATURE` header. No human approval needed. - - - - The server verifies the payment via a facilitator, settles onchain, and returns the requested data. The entire flow takes seconds. - - - -Any agent with a funded wallet can pay for any x402-enabled API — no pre-existing relationship or account required. - -[Learn more about x402 →](https://docs.cdp.coinbase.com/x402/docs/client-server-model) - -## Making x402 requests - -### CDP Agentic Wallet - -With the [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/) skills installed, your agent handles x402 payments automatically: - -```bash Terminal -npx skills add coinbase/agentic-wallet-skills -``` - -**Discover available services** using the [`search-for-service`](https://docs.cdp.coinbase.com/agentic-wallet/skills/search-for-service) skill: - -```bash Terminal -npx awal@latest x402 bazaar search "weather forecast" -``` - -**Call a paid service** using the [`pay-for-service`](https://docs.cdp.coinbase.com/agentic-wallet/skills/pay-for-service) skill: - -```bash Terminal -npx awal@latest x402 pay https://example.com/api/weather \ - -X POST \ - -d '{"query": "New York"}' -``` - -Or prompt your agent directly: - -```text -Find APIs for sentiment analysis -Call that weather API and get the forecast for New York -``` - -The [`search-for-service`](https://docs.cdp.coinbase.com/agentic-wallet/skills/search-for-service) and [`pay-for-service`](https://docs.cdp.coinbase.com/agentic-wallet/skills/pay-for-service) skills handle discovery, payment, and retries. - -[CDP Agentic Wallet skills →](https://docs.cdp.coinbase.com/agentic-wallet/skills) - -### Sponge Wallet - -[Sponge Wallet](https://www.paysponge.com) has a built-in x402 proxy that discovers services and handles payment automatically: - -**Step 1 — Discover a service:** - -```bash Terminal -curl "https://api.wallet.paysponge.com/api/discover?query=weather+forecast" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" -``` - -**Step 2 — Get service details** (required — do not skip): - -```bash Terminal -curl "https://api.wallet.paysponge.com/api/discover/{serviceId}" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" -``` - -This returns the `baseUrl`, endpoint paths, parameters, and pricing. - -**Step 3 — Call the service** (payment is automatic): - -```bash Terminal -curl -X POST "https://api.wallet.paysponge.com/api/x402/fetch" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" \ - -H "Content-Type: application/json" \ - -d '{ - "url": "https://{baseUrl}/{endpointPath}", - "method": "POST", - "body": { "query": "New York" }, - "preferred_chain": "base" - }' -``` - -[Sponge Wallet](https://www.paysponge.com) detects the `402`, pays in USDC from your wallet, and returns the API response. - -[Sponge Wallet docs →](https://wallet.paysponge.com/skill.md) - -## Error handling and retries - -| Status | Meaning | What to do | -|--------|---------|------------| -| `402` | Payment required | Parse `PAYMENT-REQUIRED` header and pay | -| `402` with `X-Payment-Error` | Payment rejected | Check wallet balance and token approval | -| `408` | Payment timeout | Retry with same or higher payment | -| `429` | Rate limit | Back off and retry after the indicated delay | - -The [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/) [`pay-for-service`](https://docs.cdp.coinbase.com/agentic-wallet/skills/pay-for-service) skill and [Sponge Wallet's](https://www.paysponge.com) x402 proxy handle retries automatically. If you're building a custom client, parse the `PAYMENT-REQUIRED` header, construct the signed payload, and retry with the `PAYMENT-SIGNATURE` header. - - - If you're using [Bankr](https://bankr.bot), no setup is required. Just prompt it directly: - - ```text - Get the current ETH price from a paid data source - Find a weather API and get the forecast for New York - Get the token balances for 0xYourAddress on Base - ``` - - Bankr handles service discovery, payment, and data extraction automatically. - - -## Video Tutorial - - -## Related - - - - Gate your own endpoints and charge other agents per request. - - - - Facilitator endpoints and protocol addresses. - - diff --git a/docs/ai-agents/plugins/morpho.mdx b/docs/ai-agents/plugins/morpho.mdx new file mode 100644 index 000000000..c49c537bd --- /dev/null +++ b/docs/ai-agents/plugins/morpho.mdx @@ -0,0 +1,184 @@ +--- +title: "Morpho Plugin" +description: "Add Morpho lending and vault operations to your AI assistant via the Morpho MCP, executed through your Base Account" +keywords: ["Morpho MCP", "Base lending AI", "Morpho vault agent", "mcp.morpho.org", "AI lending agent Base"] +--- + +import { AcceptingPaymentsDemo } from "/snippets/AcceptingPaymentsDemo.jsx" + +[Morpho](https://morpho.org) is a lending protocol on Base. The Morpho MCP server gives your assistant tools to query vaults, check markets, and prepare lending operations — which are then signed and sent through your Base Account MCP. + +## Demo + + + +## How it works + +Morpho handles the protocol layer. Your Base Account handles signing. + +```mermaid +sequenceDiagram + participant User + participant AI as AI Assistant + participant Morpho as Morpho MCP + participant BA as Base Account MCP + + User->>AI: "Deposit 100 USDC into the best vault" + AI->>Morpho: morpho_query_vaults(asset=USDC, sortBy=APY) + Morpho-->>AI: vault list with APYs + AI->>Morpho: morpho_prepare_deposit(vaultAddress, 100 USDC) + Morpho-->>AI: { calls, chainId } (simulated, unsigned) + AI->>BA: send_calls(chainId, calls) + BA-->>AI: { approvalUrl, requestId } + AI-->>User: "Please approve: [link]" + User-->>AI: approved + AI->>BA: get_request_status(requestId) + BA-->>AI: confirmed + AI-->>User: "100 USDC deposited" +``` + + +Morpho's `prepare_*` tools simulate the transaction before returning. Review the simulation output before approving — it shows expected state changes, health factors, and any warnings. + + +## Install + +Add both MCPs to your assistant: + + + + ```json claude_desktop_config.json + { + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + }, + "morpho": { + "url": "https://mcp.morpho.org/" + } + } + } + ``` + + + ```bash Terminal + claude mcp add --transport http base-account https://mcp.base.org + claude mcp add morpho --transport http https://mcp.morpho.org/ + ``` + + + ```toml codex.toml + [mcp_servers.base-account] + url = "https://mcp.base.org/" + + [mcp_servers.morpho] + url = "https://mcp.morpho.org/" + ``` + + + Add a second entry alongside `base-account` in your MCP config: + + ```json + { + "mcpServers": { + "base-account": { "url": "https://mcp.base.org" }, + "morpho": { "url": "https://mcp.morpho.org/" } + } + } + ``` + + + +## Morpho tools + +17 tools across read, write (prepare), and simulate. + +### Read + +| Tool | What it does | +|------|-------------| +| `morpho_health_check` | Check server connectivity | +| `morpho_get_supported_chains` | List supported chains | +| `morpho_query_vaults` | List vaults with filtering and sorting | +| `morpho_get_vault` | Details for a specific vault | +| `morpho_query_markets` | List markets with filtering | +| `morpho_get_market` | Details for a specific market | +| `morpho_get_positions` | All positions for an address (vaults + markets) | +| `morpho_get_token_balance` | Token balance and approval state | + +### Prepare (write via `send_calls`) + +These tools return unsigned call data. Pass the result to Base Account MCP's `send_calls` to execute. + +| Tool | What it does | +|------|-------------| +| `morpho_prepare_deposit` | Prepare vault deposit with token approvals | +| `morpho_prepare_withdraw` | Prepare vault withdrawal (supports max) | +| `morpho_prepare_supply` | Prepare market supply with approvals | +| `morpho_prepare_borrow` | Prepare market borrow with health check | +| `morpho_prepare_repay` | Prepare market repay (supports max) | +| `morpho_prepare_supply_collateral` | Supply collateral to a market | +| `morpho_prepare_withdraw_collateral` | Withdraw collateral with health check | + +### Simulate + +| Tool | What it does | +|------|-------------| +| `morpho_simulate_transactions` | Simulate transactions with post-state analysis | + +## Example prompts + +**Deposit into a vault:** +```text +Find the best USDC vault on Base by APY and deposit 100 USDC +``` + +**Check positions:** +```text +Show all my Morpho positions on Base +``` + +**Borrow against collateral:** +```text +Supply 1 ETH as collateral on Morpho and borrow 2000 USDC +``` + +**Check health:** +```text +What's my Morpho borrow health factor? +``` + +**Withdraw:** +```text +Withdraw all my USDC from Morpho vaults +``` + +## Orchestration pattern + +Every Morpho write operation follows the same pattern: + + + + Use a read tool to find the right vault or market: `morpho_query_vaults`, `morpho_get_market`, etc. + + + Call a `prepare_*` tool. Morpho simulates the operation and returns `{ calls, chainId }`. + + + Pass `calls` and `chainId` to Base Account MCP's `send_calls`. You'll get an `approvalUrl`. + + + Open the `approvalUrl`, approve the transaction, then your assistant polls `get_request_status`. + + + +## Related + + + + Full guide to `send_calls` and batching protocol interactions. + + + Full Morpho MCP documentation and prompt library. + + diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx new file mode 100644 index 000000000..29e1abbfa --- /dev/null +++ b/docs/ai-agents/quickstart.mdx @@ -0,0 +1,197 @@ +--- +title: "Quickstart" +description: "Connect the Base Account MCP to your AI assistant in under 2 minutes" +keywords: ["Base Account MCP quickstart", "mcp.base.org setup", "Claude Desktop MCP", "ChatGPT MCP", "Claude Code MCP wallet"] +--- + +import { WalletSetupDemo } from "/snippets/WalletSetupDemo.jsx" + +Connect `mcp.base.org` to your AI assistant, then send your first prompt. + +## Demo + + + +## Step 1 — Connect + + + + Open your Claude Desktop config file and add the Base Account MCP server: + + **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json` + **Windows:** `%APPDATA%\Claude\claude_desktop_config.json` + + ```json claude_desktop_config.json + { + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + } + } + } + ``` + + Restart Claude Desktop. A wallet icon will appear when the MCP is connected. + + + 1. Open the ChatGPT app + 2. Go to **Settings → Connectors** + 3. Click **Add custom connector** + 4. Enter the server URL: + + ``` + https://mcp.base.org + ``` + + 5. Save and return to a conversation. ChatGPT will prompt you to authorize when you first use a wallet tool. + + + Run this command in your terminal: + + ```bash Terminal + claude mcp add --transport http base-account https://mcp.base.org + ``` + + Then start a Claude Code session. The `base-account` MCP will be available immediately. + + To verify it's connected: + + ```bash Terminal + claude mcp list + ``` + + + ```bash Terminal + codex mcp add base-account --url https://mcp.base.org/ + ``` + + Or add to your `codex.toml`: + + ```toml codex.toml + [mcp_servers.base-account] + url = "https://mcp.base.org/" + ``` + + + Click to install automatically: + + + Add to Cursor + + + Or add manually to `~/.cursor/mcp.json`: + + ```json ~/.cursor/mcp.json + { + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + } + } + } + ``` + + + + Install in VS Code + + + Or add to your VS Code MCP config: + + ```json settings.json + { + "servers": { + "base-account": { + "type": "http", + "url": "https://mcp.base.org" + } + } + } + ``` + + + +## Step 2 — Authorize + +The first time you use a wallet tool, your assistant will redirect you to `keys.coinbase.com` to connect your Base Account. You'll need a Coinbase account. Once authorized, all transactions still require individual approval at that same URL. + +## Step 3 — Try it + +Ask your assistant: + +```text +Show me my wallets +``` + +```text +What's my USDC balance on Base? +``` + +```text +Send 1 USDC to coinbase.base.eth +``` + +Every send, swap, or sign operation will give you an approval link. Open it, review the transaction, and confirm. + +--- + +## Add a plugin — Morpho lending + +Morpho lets your assistant query vaults, check APYs, and execute lending operations on Base — then sign them through your Base Account. + +Add both MCPs to your config: + + + + ```json claude_desktop_config.json + { + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + }, + "morpho": { + "url": "https://mcp.morpho.org/" + } + } + } + ``` + + + ```bash Terminal + claude mcp add --transport http base-account https://mcp.base.org + claude mcp add morpho --transport http https://mcp.morpho.org/ + ``` + + + Add a second entry alongside `base-account`: + + ```json + "morpho": { "url": "https://mcp.morpho.org/" } + ``` + + + +Then try: + +```text +Find the best USDC vault on Base by APY and deposit 100 USDC +``` + +Morpho prepares the transaction; your Base Account signs it. See [Morpho plugin →](/ai-agents/plugins/morpho) + +## Next steps + + + + Step-by-step guides for sending, swapping, checking balance, and more. + + + Query vaults, check APYs, and execute lending operations on Base. + + + Detailed platform setup, auth flow, and approval mode explained. + + + Install the base-mcp skill for your coding assistant. + + diff --git a/docs/ai-agents/quickstart/payments.mdx b/docs/ai-agents/quickstart/payments.mdx deleted file mode 100644 index 79dd9f679..000000000 --- a/docs/ai-agents/quickstart/payments.mdx +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: "Get Started with Payments" -description: "Build an agent that makes and accepts x402 payments on Base in under 10 minutes" -keywords: ["x402 quickstart", "agent payments", "OpenClaw payments", "AI agent pay for API", "accept payments agent"] ---- - -import { PaymentsQuickstartDemo } from "/snippets/PaymentsQuickstartDemo.jsx" - -This guide gets you from zero to a working agent that makes a paid x402 API request and exposes its own paid endpoint — all in under 10 minutes. - -## Mock Demo - - - - -## Install OpenClaw - - - - **macOS / Linux:** - - ```bash Terminal - curl -fsSL https://openclaw.ai/install.sh | bash - ``` - - **Windows (PowerShell):** - - ```powershell Terminal - iwr -useb https://openclaw.ai/install.ps1 | iex - ``` - - Verify the installation: - - ```bash Terminal - openclaw --version - ``` - - - - ```bash Terminal - openclaw onboard --install-daemon - ``` - - Follow the prompts to connect your LLM provider and set up your wallet plugin. - - - - ```bash Terminal - openclaw gateway --port 18789 - ``` - - Open `http://127.0.0.1:18789/` to verify the gateway is live. - - - - -**Claude Code, Codex, and OpenCode users** — the wallet skills and x402 payment tools below are compatible with any skills-enabled AI coding tool. Run the same `npx skills add` commands and the capabilities work identically. - - -## Configure a wallet - -Install the CDP Agentic Wallet skills: - -```bash Terminal -npx skills add coinbase/agentic-wallet-skills -``` - -Then authenticate: - -```text -Sign in to my wallet with your@email.com -``` - -Or use a [Sponge Wallet](https://www.paysponge.com) with native x402 support — see [wallet setup](/ai-agents/setup/wallet-setup) for all options. - -## Make your first x402 payment - -Ask your agent to discover and call a paid API: - -```text -Find a weather API and get the forecast for New York -``` - -The `search-for-service` and `pay-for-service` skills handle discovery, payment, and retries automatically. Your agent pays in USDC, gets the data, and returns the result — no API keys, no subscriptions. - -To make a direct x402 request with Sponge Wallet: - -```bash Terminal -curl -X POST "https://api.wallet.paysponge.com/api/x402/fetch" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" \ - -H "Content-Type: application/json" \ - -d '{ - "url": "https://api.example.com/paid-endpoint", - "method": "GET", - "preferred_chain": "base" - }' -``` - -## Gate your own endpoint with x402 - -Ask your agent to expose a paid API: - -```text -Set up a paid endpoint for my market data at $0.01 per request -``` - -The `monetize-service` skill (`npx skills add coinbase/agentic-wallet-skills`) configures the x402 gating and deploys the endpoint. Other agents can now discover and pay for your service automatically. - -Or use `x402-express` for a custom server — see [Accepting payments](/ai-agents/payments/accepting-payments). - -## Next steps - - - - Deep dive into how x402 works, supported networks, and error handling. - - - - Set up server-side x402 gating with OpenClaw skills or custom middleware. - - - - Configure Bankr, CDP, or Sponge for your agent. - - - - Register your agent for discoverability and identity verification. - - diff --git a/docs/ai-agents/quickstart/trading.mdx b/docs/ai-agents/quickstart/trading.mdx deleted file mode 100644 index 23219ecb1..000000000 --- a/docs/ai-agents/quickstart/trading.mdx +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: "Get Started with Trading" -description: "Build an agent that fetches live market data and executes token swaps on Base" -keywords: ["trading agent quickstart", "OpenClaw trading", "Base trading agent", "token swap agent", "x402 market data"] ---- - -import { TradingQuickstartDemo } from "/snippets/TradingQuickstartDemo.jsx" - -This guide gets you from zero to a working agent that fetches live price data via x402 and executes a token swap on Base. - -## Mock Demo - - - - -## Install OpenClaw - - - - **macOS / Linux:** - - ```bash Terminal - curl -fsSL https://openclaw.ai/install.sh | bash - ``` - - **Windows (PowerShell):** - - ```powershell Terminal - iwr -useb https://openclaw.ai/install.ps1 | iex - ``` - - Verify: - - ```bash Terminal - openclaw --version - ``` - - - - ```bash Terminal - openclaw onboard --install-daemon - ``` - - - - ```bash Terminal - openclaw gateway --port 18789 - ``` - - - - -**Claude Code, Codex, and OpenCode users** — the wallet and trading skills below are compatible with any skills-enabled AI coding tool. Run the same `npx skills add` commands from within your tool. - - -## Configure a trading wallet - -Bankr provides cross-chain wallet access with gas sponsorship and built-in swap support — ideal for trading agents: - -```text -install the bankr skill from https://github.com/BankrBot/skills -``` - -Create a dedicated account at [bankr.bot](https://bankr.bot) and generate an API key at [bankr.bot/api](https://bankr.bot/api). - -For [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/) or [Sponge Wallet](https://www.paysponge.com), see [wallet setup](/ai-agents/setup/wallet-setup). - -## Execute a swap - -Ask your agent to execute a trade using wallet-native tools: - -```text -Buy $50 of ETH on Base -``` - -With Bankr or CDP Agentic Wallet, built-in swap tools handle the trade — no external DEX integration needed. The wallet constructs, signs, and broadcasts the transaction. - -For best execution on Base, use the preconf endpoint to simulate before signing: - -```text -Simulate buying $50 of ETH then execute if the price impact is below 1% -``` - -## Next steps - - - - Full catalog of x402 data sources for trading agents. - - - - Flashblocks timing, fee calibration, and failure modes on Base. - - - - Configure Bankr, CDP, or Sponge for your agent. - - - - How x402 works for data fetching and payments. - - diff --git a/docs/ai-agents/setup/agent-registration.mdx b/docs/ai-agents/setup/agent-registration.mdx deleted file mode 100644 index ac68e1217..000000000 --- a/docs/ai-agents/setup/agent-registration.mdx +++ /dev/null @@ -1,188 +0,0 @@ ---- -title: "Agent Registration & Identity" -description: "Register your agent's identity onchain, get a Basename, and authenticate with services using Sign In With Agent (SIWA)" -keywords: ["ERC-8004", "agent registration", "Basename agent", "agent identity", "SIWA", "Sign In With Agent", "ERC-8128", "onchain identity Base"] ---- - -import { AgentRegistrationDemo } from "/snippets/AgentRegistrationDemo.jsx" - -When your agent calls a service, how does that service know it's really your agent? When your agent receives a response, how does it know the response is legitimate? Registration and identity verification solve both problems. - -## Mock Demo - - - -## Why register? - -- **Discoverability** — other agents and services can find your agent by querying the public registry -- **SIWA authentication** — services use your registration to verify that requests genuinely come from your agent -- **Reputation** — the reputation registry accumulates trust signals that other agents can query before interacting with yours - -## Get a Basename for your agent - -A Basename gives your agent a human-readable identity (e.g., `myagent.base.eth`) that resolves to its wallet address. Register at [base.org/names](https://www.base.org/names). - -## Register in the ERC-8004 registry - -The [ERC-8004](https://www.8004.org/) standard is an onchain NFT registry where agents publish their identity: name, description, endpoints, and public key. - - - - Use 8004scan.io to register and explore registered agents through a web interface — no code required. - - - Use the Agent0 SDK to register your agent programmatically and manage its onchain profile. - - - -A registry entry includes your agent's name and description, the endpoints where it can be reached, and a key pair that ties the agent's identity to its cryptographic credentials. - -The canonical registry addresses are at [8004scan.io](https://www.8004scan.io). - -[Learn more about ERC-8004 →](https://www.8004.org/) - -## Verify identity at runtime (ERC-8128) - -Registration tells the world your agent exists. The **ERC-8128** standard lets your agent prove it's really yours with every request: - - - - Your agent registers its identity and public key in the ERC-8004 registry. This is a one-time setup step. - - - - When your agent calls a service, it signs the request using its private key. This creates a cryptographic signature unique to that specific request. - - - - The service looks up your agent's public key from the registry, then checks the signature. If it matches, the service knows the request came from your registered agent. - - - -This works in both directions — your agent can verify a service's responses are authentic by checking the service's signature against the registry. - -[ERC-8128 specification →](https://erc8128.slice.so/concepts/overview) - -## Sign In With Agent (SIWA) - -[SIWA](https://siwa.id) bundles ERC-8004 registration and ERC-8128 signing into a single SDK — similar to how "Sign in with Google" bundles OAuth into one integration. - - -**Start with SIWA** for the simplest integration path. Use ERC-8004 and ERC-8128 directly only if you need fine-grained control over registration and verification. - - -### Agent-side integration - -Install the SIWA SDK: - -```bash Terminal -npm install @buildersgarden/siwa -``` - -Choose a signer based on your wallet provider. SIWA supports private keys, Bankr, Circle, Openfort, Privy, and smart contract accounts: - -```typescript TypeScript -import { createLocalAccountSigner } from "@buildersgarden/siwa/signer"; -import { privateKeyToAccount } from "viem/accounts"; - -const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); -const signer = createLocalAccountSigner(account); -``` - -Request a nonce from the service, then sign and submit a SIWA message: - -```typescript TypeScript -import { signSIWAMessage } from "@buildersgarden/siwa"; - -// Step 1: Request a nonce from the service -const nonceResponse = await fetch("https://api.example.com/siwa/nonce", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ address: await signer.getAddress() }), -}); -const { nonce, issuedAt } = await nonceResponse.json(); - -// Step 2: Sign the SIWA message -const { message, signature } = await signSIWAMessage( - { - domain: "api.example.com", - uri: "https://api.example.com/siwa", - agentId: 42, // your ERC-8004 token ID - agentRegistry: "eip155:8453:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432", - chainId: 8453, - nonce, - issuedAt, - }, - signer -); - -// Step 3: Submit for verification and receive a receipt -const verifyResponse = await fetch("https://api.example.com/siwa/verify", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ message, signature }), -}); -const { receipt } = await verifyResponse.json(); -``` - -Use the receipt to sign subsequent requests with ERC-8128: - -```typescript TypeScript -import { signAuthenticatedRequest } from "@buildersgarden/siwa/erc8128"; - -const request = new Request("https://api.example.com/action", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ action: "transfer" }), -}); - -const signedRequest = await signAuthenticatedRequest(request, receipt, signer, 8453); -const response = await fetch(signedRequest); -``` - -### Server-side verification - -Services that accept SIWA-authenticated agents implement two endpoints: one to issue nonces and one to verify signatures. - -```typescript TypeScript -import { verifySIWA, createSIWANonce } from "@buildersgarden/siwa"; -import { createReceipt } from "@buildersgarden/siwa/receipt"; -import { createPublicClient, http } from "viem"; -import { base } from "viem/chains"; - -const client = createPublicClient({ chain: base, transport: http() }); - -// POST /siwa/nonce -const { nonce, issuedAt } = await createSIWANonce({ address, agentId, agentRegistry }, client); - -// POST /siwa/verify -const result = await verifySIWA(message, signature, "api.example.com", nonceValid, client); -if (result.success) { - const { receipt } = createReceipt({ address: result.address, agentId: result.agentId }); - return { receipt }; -} -``` - -SIWA ships drop-in middleware for Express, Next.js, Hono, and Fastify. See the [SIWA documentation](https://siwa.id/docs) for framework-specific examples, replay protection, and x402 payment integration. - -## Video Tutorial - - - -## Related - - - - Browse and verify registered agents and registry addresses on Base. - - - - Pay for API access with stablecoins using the x402 protocol. - - diff --git a/docs/ai-agents/setup/index.mdx b/docs/ai-agents/setup/index.mdx new file mode 100644 index 000000000..255d22206 --- /dev/null +++ b/docs/ai-agents/setup/index.mdx @@ -0,0 +1,178 @@ +--- +title: "Setup" +description: "Connect the Base Account MCP to Claude Desktop, ChatGPT, Claude Code, Codex, Cursor, VS Code, and more" +keywords: ["mcp.base.org setup", "Base Account MCP install", "Claude Desktop MCP config", "ChatGPT MCP connector", "Claude Code MCP"] +--- + +import { X402PayDemo } from "/snippets/x402PayDemo.jsx" + +The Base Account MCP server lives at `https://mcp.base.org`. Add it to your AI assistant once and your wallet tools are available in every conversation. + +## Authentication + +Connecting `mcp.base.org` requires a **Coinbase account** with a Base Account (smart wallet). When you first use a transactional tool (send, swap, sign), your assistant will return an `approvalUrl` — open it at `keys.coinbase.com` to authorize your Base Account and approve the transaction. + + +Every individual transaction requires approval at `keys.coinbase.com`. Your assistant never has unilateral access to your funds. + + +## Platform setup + +### Claude Desktop + +Open your config file and add the `base-account` server: + +| Platform | Config path | +|----------|-------------| +| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` | +| Windows | `%APPDATA%\Claude\claude_desktop_config.json` | + +```json claude_desktop_config.json +{ + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + } + } +} +``` + +Restart Claude Desktop. The wallet MCP will show as connected in the toolbar. + +--- + +### ChatGPT + +1. Open the **ChatGPT** app +2. Go to **Settings → Connectors** +3. Click **Add custom connector** +4. Enter `https://mcp.base.org` as the server URL +5. Save + +On first use, ChatGPT will prompt you to authorize your Coinbase account. + +--- + +### Claude Code + +```bash Terminal +claude mcp add --transport http base-account https://mcp.base.org +``` + +This writes to your project's `.claude/settings.json`. To add globally (all projects): + +```bash Terminal +claude mcp add --transport http --scope user base-account https://mcp.base.org +``` + +Verify the connection: + +```bash Terminal +claude mcp list +``` + +--- + +### Codex + +```bash Terminal +codex mcp add base-account --url https://mcp.base.org/ +``` + +Or add to `codex.toml`: + +```toml codex.toml +[mcp_servers.base-account] +url = "https://mcp.base.org/" +``` + +--- + +### Cursor + + + One-click install in Cursor + + +Or add manually to `~/.cursor/mcp.json`: + +```json ~/.cursor/mcp.json +{ + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + } + } +} +``` + +--- + +### VS Code + + + Install in VS Code + + +Or add to your VS Code MCP settings: + +```json settings.json +{ + "servers": { + "base-account": { + "type": "http", + "url": "https://mcp.base.org" + } + } +} +``` + +--- + +### Windsurf + +Add to `~/.codeium/windsurf/mcp_config.json`: + +```json mcp_config.json +{ + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + } + } +} +``` + +--- + +## Approval mode + + + +All write operations (send, swap, sign, send_calls) work in **approval mode**: + + + + You ask your assistant to send funds, swap tokens, or sign a message. + + + Your assistant returns an `approvalUrl` (at `keys.coinbase.com`) and a `requestId`. + + + Open the link, review the transaction details, and confirm. Nothing is signed until you do. + + + Your assistant polls `get_request_status` with the `requestId` and confirms completion once you've approved. + + + +## Next steps + + + + Step-by-step guides for sending, swapping, checking balance, and more. + + + Add Morpho for lending and vault operations on Base. + + diff --git a/docs/ai-agents/setup/wallet-setup.mdx b/docs/ai-agents/setup/wallet-setup.mdx deleted file mode 100644 index 2c48d5a80..000000000 --- a/docs/ai-agents/setup/wallet-setup.mdx +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: "Wallet Setup for Agents" -description: "Give your AI agent a dedicated wallet on Base to hold funds, send payments, sign messages, and interact with onchain protocols securely." -keywords: ["AI agent wallet", "Bankr wallet", "CDP agentic wallet", "Sponge wallet", "onchain AI agent", "agent wallet setup"] ---- - -import { WalletSetupDemo } from "/snippets/WalletSetupDemo.jsx" - -An onchain wallet gives your agent the ability to hold funds, authorize transactions, and sign messages. Without one, your agent can read data but can't pay for services, receive payments, or prove its identity. - -## Mock Demo - - - -## Why your agent needs a dedicated wallet - -An AI agent *could* generate its own wallet by creating a random private key through prompting, but this is unsafe: - -- The private key appears in the agent's conversation context, where it can be logged, cached, or leaked through middleware -- Any system with access to the agent's prompt history could extract the key -- If the key is compromised, all funds in the wallet are permanently lost - -Dedicated wallet services solve this by managing keys in secure infrastructure separated from your agent's runtime. Your agent requests transactions without ever seeing the private key. - -## Choose a wallet - - - - Every Bankr agent gets a cross-chain wallet on Base, Ethereum, Solana, Polygon, and Unichain. Gas is sponsored on supported chains. Built-in swap tools make Bankr ideal for trading agents. - - Install the Bankr skill from your agent chat: - - ```text - install the bankr skill from https://github.com/BankrBot/skills - ``` - - Create a dedicated account at [bankr.bot](https://bankr.bot) and generate an API key at [bankr.bot/api](https://bankr.bot/api). Don't use your personal Bankr account — keep your agent's wallet separate. - - [Bankr docs →](https://docs.bankr.bot) - - - - Coinbase's standalone wallet for AI agents. Authentication is via email OTP — no API keys required in your agent. Private keys stay in Coinbase's secure infrastructure. Native x402 payment support is built in. - - Install the pre-built wallet skills: - - ```bash Terminal - npx skills add coinbase/agentic-wallet-skills - ``` - - Then ask your agent to authenticate: - - ```text - Sign in to my wallet with your@email.com - ``` - - Skills include: `authenticate-wallet`, `fund`, `send-usdc`, `trade`, `pay-for-service`, `monetize-service`, and more. Operates on Base. - - [CDP Agentic Wallet docs →](https://docs.cdp.coinbase.com/agentic-wallet/welcome) - - - - A multi-chain agent wallet with native x402 payment handling, built-in token swaps, and cross-chain bridges across Base, Ethereum, and Solana. Sponge's x402 proxy handles discovery, payment, and retries automatically. - - Register your agent to get a wallet immediately: - - ```bash Terminal - curl -X POST https://api.wallet.paysponge.com/api/agents/register \ - -H "Sponge-Version: 0.2.1" \ - -H "Content-Type: application/json" \ - -d '{"name": "my-agent", "agentFirst": true}' - ``` - - Store the returned `apiKey`: - - ```bash Terminal - export SPONGE_API_KEY=sponge_live_... - ``` - - [Sponge Wallet docs →](https://wallet.paysponge.com/skill.md) - - - - -**Claude Code, Codex, and OpenCode users** — the wallet skills above work with any skills-enabled AI coding tool. Run the same `npx skills add` command from within your coding tool to get the same onchain capabilities. - - -## What your agent can do with a wallet - -Once your agent has a wallet, it can: - -- **Hold stablecoins**: receive and store USDC or other tokens -- **Send and receive payments**: transfer funds to other wallets, pay for API access, or receive payments for services -- **Sign messages**: cryptographically prove that a message or request came from your agent (used for identity verification) -- **Interact with protocols**: call smart contracts to swap tokens, provide liquidity, or use other onchain services - - - -## Next step - - - Register your agent for discoverability and identity verification. - diff --git a/docs/ai-agents/skills/index.mdx b/docs/ai-agents/skills/index.mdx index 6ffde202c..1b31135a1 100644 --- a/docs/ai-agents/skills/index.mdx +++ b/docs/ai-agents/skills/index.mdx @@ -1,41 +1,42 @@ --- -title: "Overview" -description: "Installable agent capabilities for wallets, payments, and trading on Base" -keywords: ["agent skills", "Bankr", "CDP agentic wallet", "Sponge wallet", "x402 skills", "trading agent", "Base agent"] +title: "Skills" +description: "Install skills to give your AI coding assistant deep context on Base Account MCP tools and CDP Agentic Wallet capabilities" +keywords: ["base-mcp skill", "CDP agentic wallet skill", "Base skills", "agent skills", "npx skills add base"] --- -Skills are installable knowledge packs that give your AI agent specific onchain capabilities — a wallet, payment handling, market data access, or trade execution. Install a skill and your agent knows what to do without any custom integration code. +Skills are installable knowledge packs that give your AI coding assistant deep context on specific APIs and tools — so it knows what to do without custom integration code. - - - Cross-chain wallet with built-in swaps, gas sponsorship, and token launching. - +## base-mcp skill - - Email-authenticated wallet on Base with x402 payment skills bundled in. - +The `base-mcp` skill gives your coding assistant full context on the Base Account MCP: all 9 tools, when to use them, approval mode patterns, and how to orchestrate with protocol plugins like Morpho. - - Multi-chain wallet with native x402 proxy, swaps, bridges, and banking. - +```bash Terminal +npx skills add base/base-skills --skill base-mcp +``` - - Discover, pay for, and monetize x402 API services via CDP Agentic Wallet. - +The skill uses progressive context sharing — it loads detailed reference docs only for the task at hand, keeping context tight. - - Sponge's built-in x402 proxy — discover and pay for services automatically. - +[base/base-skills on GitHub →](https://github.com/base/base-skills) - - Price feeds, market cap, and OHLCV data via x402 — no API key required. - +## CDP Agentic Wallet skills - - Token balances, NFT metadata, portfolio data, and prices via x402 SIWE auth. - +For x402 payments (paying for API access per-request in stablecoins), use the CDP Agentic Wallet skill bundle: + +```bash Terminal +npx skills add coinbase/agentic-wallet-skills +``` - - Execute token swaps using wallet-native skills across Bankr, CDP, and Sponge. +Includes `pay-for-service`, `search-for-service`, `monetize-service`, `send-usdc`, `trade`, and more. + + + + Email-authenticated wallet with x402 payment skills bundled in. + + + Discover, pay for, and monetize x402 API services. + + +x402 support for the Base Account MCP is coming soon. See [Payments](/ai-agents/payments) for details. + diff --git a/docs/ai-agents/skills/payments/cdp-payment-skills.mdx b/docs/ai-agents/skills/payments/cdp-payment-skills.mdx index e49427ac7..70e271823 100644 --- a/docs/ai-agents/skills/payments/cdp-payment-skills.mdx +++ b/docs/ai-agents/skills/payments/cdp-payment-skills.mdx @@ -1,10 +1,14 @@ --- title: "CDP Payment Skills" -description: "Skills for discovering, paying for, and monetizing x402 API services via the CDP Agentic Wallet" -keywords: ["CDP payment skills", "search-for-service skill", "pay-for-service skill", "monetize-service skill", "x402 bazaar skill"] +description: "x402 payment skills for discovering, paying for, and monetizing API services — part of the CDP Agentic Wallet skill bundle" +keywords: ["CDP payment skills", "x402 skills", "pay-for-service skill", "search-for-service skill", "monetize-service skill"] --- -Three skills from the CDP Agentic Wallet bundle cover the full x402 commerce loop: finding paid APIs, calling them with automatic payment, and gating your own endpoints to charge other agents. +The CDP payment skills — included in the CDP Agentic Wallet bundle — give your agent the ability to discover x402-compatible APIs, pay for them per-request, and expose its own paid endpoints. + + +x402 support for the Base Account MCP is coming soon. Until then, these skills require the CDP Agentic Wallet. See [Payments](/ai-agents/payments) for context. + ## Install @@ -12,9 +16,7 @@ Three skills from the CDP Agentic Wallet bundle cover the full x402 commerce loo npx skills add coinbase/agentic-wallet-skills ``` -Included in the same package as the [CDP Agentic Wallet](/ai-agents/skills/wallets/cdp-agentic-wallet). No separate install needed. - -## What the skill covers +## Payment skills | Skill | What it does | |-------|-------------| diff --git a/docs/ai-agents/skills/payments/sponge-x402.mdx b/docs/ai-agents/skills/payments/sponge-x402.mdx deleted file mode 100644 index 0708d7116..000000000 --- a/docs/ai-agents/skills/payments/sponge-x402.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: "Sponge x402" -description: "Skill for discovering and paying for x402 services automatically using Sponge Wallet's built-in proxy" -keywords: ["Sponge x402 skill", "x402 proxy skill", "automatic x402 payment skill", "discover x402 service skill", "paysponge x402 skill"] ---- - -Sponge's built-in x402 proxy handles service discovery, payment signing, and retries automatically. The skill lets your agent find and pay for any x402-gated API in a single step — no manual 402 handling, no retry logic. - -## Install - -Included with [Sponge Wallet](/ai-agents/skills/wallets/sponge-wallet). No separate install needed. - -## What the skill covers - -| Capability | Description | -|------------|-------------| -| **Service discovery** | Search the x402 catalog by keyword | -| **Automatic payment** | Detect a 402, pay in USDC, and retry transparently | -| **Payment links** | Create reusable payment links to gate your own services | - -## Example prompts - -```text -Find a weather API and pay for it using Sponge -``` - -```text -Search for sentiment analysis APIs in the x402 catalog -``` - -```text -Create a payment link for my market data service at $0.01 per request -``` - -## Reference - -- [Sponge Wallet skill doc →](https://wallet.paysponge.com/skill.md) diff --git a/docs/ai-agents/skills/trading/alchemy-agentic-gateway.mdx b/docs/ai-agents/skills/trading/alchemy-agentic-gateway.mdx deleted file mode 100644 index 5825974c3..000000000 --- a/docs/ai-agents/skills/trading/alchemy-agentic-gateway.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "Alchemy Agentic Gateway" -description: "Skill for accessing Alchemy's blockchain APIs — token balances, NFTs, portfolio data, and prices — via x402 SIWE auth" -keywords: ["Alchemy agentic gateway skill", "Alchemy x402 skill", "onchain data agent skill", "SIWE x402 skill", "alchemy skill agent"] ---- - -The Alchemy Agentic Gateway skill gives your agent access to Alchemy's enhanced blockchain APIs at `https://x402.alchemy.com` — token balances, NFT metadata, portfolio data, token prices, and decoded transaction history — authenticated via Sign-In With Ethereum (SIWE) and paid per call via x402. - -## Install - -```bash Terminal -npx @alchemy/x402 wallet generate -``` - -Then follow the skill setup to sign a SIWE auth token. The full setup guide is in the skill reference below. - -## What the skill covers - -| Data | Description | -|------|-------------| -| **Token balances** | ERC-20 balances for any address on Base | -| **NFT metadata** | Token attributes, images, and ownership | -| **Portfolio data** | Multi-chain token holdings with metadata | -| **Token prices** | Current prices by symbol | -| **Transaction history** | Decoded asset transfers | - -## Example prompts - -```text -Check the token balances at 0xYourAddress on Base -``` - -```text -Get the portfolio for 0xYourAddress across all chains -``` - -```text -What's the current price of ETH and USDC? -``` - -```text -Show me the NFTs owned by 0xYourAddress -``` - -## Reference - -- [Alchemy Agentic Gateway skill →](https://github.com/alchemyplatform/skills/tree/main/skills/agentic-gateway) diff --git a/docs/ai-agents/skills/trading/coingecko.mdx b/docs/ai-agents/skills/trading/coingecko.mdx deleted file mode 100644 index bdbf7bd4f..000000000 --- a/docs/ai-agents/skills/trading/coingecko.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: "CoinGecko" -description: "Skill for fetching live crypto price feeds, market cap, and OHLCV data via x402 — no API key required" -keywords: ["CoinGecko skill", "price feed skill", "crypto market data x402 skill", "agent data source skill", "CoinGecko x402 agent"] ---- - -CoinGecko provides cryptocurrency price feeds, market cap data, and historical OHLCV via x402-enabled endpoints. Your agent pays per call in USDC — no API key, no subscription, no rate-limit tier. - -## Install - -Access CoinGecko data through your existing wallet skill: - -- **CDP Agentic Wallet** — use the `pay-for-service` skill (`npx skills add coinbase/agentic-wallet-skills`) -- **Sponge Wallet** — use the built-in x402 proxy (no extra install) -- **Bankr** — prompt directly, Bankr handles discovery and payment - -## What the skill covers - -| Data | Description | -|------|-------------| -| **Price feeds** | Current price for any asset in USD or other currencies | -| **Market data** | Market cap, volume, and circulating supply | -| **Historical OHLCV** | Open/high/low/close/volume over any time range | - -## Example prompts - -```text -Get the current ETH price from CoinGecko -``` - -```text -Get current prices for ETH, BTC, and SOL -``` - -```text -Fetch the 7-day OHLCV for Bitcoin from CoinGecko -``` - -```text -What's the market cap of Ethereum? -``` - -## Reference - -- [pay-for-service skill →](https://docs.cdp.coinbase.com/agentic-wallet/skills/pay-for-service) -- [CoinGecko API docs →](https://docs.coingecko.com) diff --git a/docs/ai-agents/skills/trading/swap-execution.mdx b/docs/ai-agents/skills/trading/swap-execution.mdx deleted file mode 100644 index 8a6d005ea..000000000 --- a/docs/ai-agents/skills/trading/swap-execution.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Swap Execution" -description: "Skills for executing token swaps on Base using wallet-native tools across Bankr, CDP Agentic Wallet, and Sponge" -keywords: ["swap execution skill", "token swap agent skill", "Bankr swap skill", "CDP trade skill", "Sponge swap skill"] ---- - -Bankr, CDP Agentic Wallet, and Sponge Wallet all include built-in swap skills — no external DEX integration required. Install any of the three wallet skills and your agent can trade tokens on Base with a simple prompt. - -## Install - -Choose the wallet skill that fits your agent: - -| Wallet | Install | -|--------|---------| -| **Bankr** | `install the bankr skill from https://github.com/BankrBot/skills` | -| **CDP Agentic Wallet** | `npx skills add coinbase/agentic-wallet-skills` | -| **Sponge Wallet** | Register via `https://api.wallet.paysponge.com/api/agents/register` | - -## What the skill covers - -| Capability | Bankr | CDP | Sponge | -|------------|-------|-----|--------| -| Token swaps on Base | ✓ | ✓ | ✓ | -| Cross-chain swaps | ✓ | — | ✓ (via deBridge) | -| Gas sponsorship | ✓ | ✓ | — | -| Preconf simulation | ✓ | ✓ | ✓ | - -## Example prompts - -```text -Buy $50 of ETH on Base -``` - -```text -Swap 100 USDC for ETH at market price -``` - -```text -Simulate buying $50 of ETH then execute if the price impact is below 1% -``` - -```text -Trade 0.01 ETH for USDC -``` - -## Reference - -- [Bankr docs →](https://docs.bankr.bot) -- [CDP trade skill →](https://docs.cdp.coinbase.com/agentic-wallet/skills) -- [Sponge skill doc →](https://wallet.paysponge.com/skill.md) diff --git a/docs/ai-agents/skills/wallets/bankr.mdx b/docs/ai-agents/skills/wallets/bankr.mdx deleted file mode 100644 index 051841362..000000000 --- a/docs/ai-agents/skills/wallets/bankr.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Bankr" -description: "Skill that gives your AI agent a cross-chain wallet with built-in swaps, gas sponsorship, and token launching" -keywords: ["Bankr skill", "agent wallet skill", "cross-chain wallet agent", "Bankr AI agent", "bankr.bot skill"] ---- - -The Bankr skill gives your AI agent a self-custodied wallet across Base, Ethereum, Solana, Polygon, and Unichain. Gas is sponsored on supported chains, swap tools handle trades natively, and agents can launch tokens and earn trading fees to fund their own compute. - -## Install - -From your agent chat: - -```text -install the bankr skill from https://github.com/BankrBot/skills -``` - -Then create a dedicated account at [bankr.bot](https://bankr.bot) and generate an API key at [bankr.bot/api](https://bankr.bot/api). - -## What the skill covers - -| Capability | Description | -|------------|-------------| -| **Cross-chain wallet** | Hold and transfer funds on Base, ETH, Solana, Polygon, and Unichain | -| **Gas sponsorship** | Transactions on supported chains don't require ETH for gas | -| **Token swaps** | Buy and sell tokens with wallet-native tools — no DEX integration needed | -| **Token launching** | Deploy tokens on Base and redirect trading fees to the agent | -| **Trading signals** | Base network signals via the `bankr-signals` skill | - -## Example prompts - -```text -Buy $50 of ETH on Base -``` - -```text -Swap 100 USDC for ETH at market price -``` - -```text -Check my wallet balance across all chains -``` - -```text -Send 10 USDC to 0xRecipientAddress -``` - -## Reference - -- [Bankr docs →](https://docs.bankr.bot) -- [Bankr skills on GitHub →](https://github.com/BankrBot/skills) diff --git a/docs/ai-agents/skills/wallets/cdp-agentic-wallet.mdx b/docs/ai-agents/skills/wallets/cdp-agentic-wallet.mdx index 27f44d1a9..f50e28564 100644 --- a/docs/ai-agents/skills/wallets/cdp-agentic-wallet.mdx +++ b/docs/ai-agents/skills/wallets/cdp-agentic-wallet.mdx @@ -1,10 +1,14 @@ --- title: "CDP Agentic Wallet" -description: "Skill that gives your AI agent an email-authenticated wallet on Base with x402 payments built in" -keywords: ["CDP agentic wallet skill", "coinbase agent wallet skill", "awal skill", "x402 agent skill", "npx skills add coinbase"] +description: "Email-authenticated wallet on Base with x402 payment skills — use this for agents that need to pay for or accept API payments" +keywords: ["CDP agentic wallet skill", "x402 agent wallet", "coinbase agentic wallet skill", "awal skill", "npx skills add coinbase"] --- -The CDP Agentic Wallet skill gives your AI agent a managed wallet on Base authenticated via email OTP — no private keys in the agent's context. The skill bundle includes seven capabilities covering authentication, funding, sending, trading, and x402 payments. +The CDP Agentic Wallet is the recommended path for agents that need **x402 payment capabilities** — paying for API access per-request in stablecoins, or charging other agents for your services. + + +For wallet operations (sending, swapping, checking balances), use the [Base Account MCP](/ai-agents/quickstart) instead. CDP Agentic Wallet is specifically the right choice when you need x402 protocol support. + ## Install @@ -30,14 +34,6 @@ npx skills add coinbase/agentic-wallet-skills Sign in to my wallet with your@email.com ``` -```text -Send 10 USDC to 0xRecipientAddress -``` - -```text -Trade 0.01 ETH for USDC -``` - ```text Find a weather API and get the forecast for New York ``` diff --git a/docs/ai-agents/skills/wallets/sponge-wallet.mdx b/docs/ai-agents/skills/wallets/sponge-wallet.mdx deleted file mode 100644 index f90cc9b79..000000000 --- a/docs/ai-agents/skills/wallets/sponge-wallet.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Sponge Wallet" -description: "Skill that gives your AI agent a multi-chain wallet with native x402 payments, swaps, bridges, and banking" -keywords: ["Sponge wallet skill", "paysponge skill", "x402 proxy skill", "multi-chain agent wallet skill", "sponge skill.md"] ---- - -The Sponge Wallet skill gives your AI agent a multi-chain wallet covering Base, Ethereum, and Solana. It includes a native x402 payment proxy, token swaps, cross-chain bridges, prediction market trading, and banking integrations. - -## Install - -Register your agent to receive a wallet and API key: - -```text -Register my agent with Sponge Wallet using the API at https://api.wallet.paysponge.com/api/agents/register -``` - -Or read the full skill reference your agent can follow: - -```text -Read the Sponge skill doc at https://wallet.paysponge.com/skill.md -``` - -## What the skill covers - -| Capability | Description | -|------------|-------------| -| **Multi-chain wallet** | Hold and transfer funds on Base, Ethereum, and Solana | -| **Native x402 proxy** | Discover services, pay, and get responses in one step | -| **Token swaps** | Swap tokens on Base and Solana DEXs | -| **Cross-chain bridges** | Bridge assets across chains via deBridge | -| **Prediction markets** | Trade on Polymarket and Hyperliquid | -| **Banking** | Virtual bank accounts and ACH payouts via Bridge.xyz | - -## Example prompts - -```text -Check my Sponge wallet balance -``` - -```text -Swap 100 USDC for ETH on Base using Sponge -``` - -```text -Find a weather API and pay for it using my Sponge wallet -``` - -```text -Bridge 50 USDC from Base to Solana -``` - -## Reference - -- [Sponge Wallet skill doc →](https://wallet.paysponge.com/skill.md) diff --git a/docs/ai-agents/trading/data-fetching.mdx b/docs/ai-agents/trading/data-fetching.mdx deleted file mode 100644 index 317e5da3e..000000000 --- a/docs/ai-agents/trading/data-fetching.mdx +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: "Fetching Market Data" -description: "Use x402 to access live market data from CoinGecko, Alchemy, and other sources — no API key management required" -keywords: ["x402 market data", "trading agent data", "CoinGecko x402", "Alchemy x402", "pay per call data", "agent data fetching"] ---- - -import { DataFetchingDemo } from "/snippets/DataFetchingDemo.jsx" - -x402 is well-suited for trading data: your agent pays per call in USDC, with no API key registration, subscription management, or rate-limit tiers to negotiate. The agent gets the data, the provider gets paid — that's the entire relationship. - -## Mock Demo - - - -## Why x402 for market data - -- **No API key management** — your agent pays on demand; no credentials to rotate or store securely -- **Pay only for what you use** — no monthly subscription for data you might not always need -- **Works across any wallet** — [Sponge Wallet's](https://www.paysponge.com) x402 proxy, [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/) skills, and `x402-axios` all handle payment automatically -- **Composable** — your agent can call multiple data providers in the same session, paying each separately - -## Discovering x402-compatible endpoints - -x402-compatible services publish a discovery document at `/.well-known/x402.json`. You can also browse the Bazaar catalog for a curated list of x402 data providers. - - - - Use the [`search-for-service`](https://docs.cdp.coinbase.com/agentic-wallet/skills/search-for-service) skill to search the x402 Bazaar: - - ```bash Terminal - npx awal@latest x402 bazaar search "price feed" - ``` - - To browse all available resources: - - ```bash Terminal - npx awal@latest x402 bazaar list --network base - ``` - - - ```bash Terminal - curl "https://api.wallet.paysponge.com/api/discover?query=price+feed" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" - ``` - - - -## Example x402 data sources - -### CoinGecko — price feeds - -CoinGecko provides cryptocurrency price feeds, market cap data, and historical OHLCV via x402-enabled endpoints. - -Fetch the current ETH price: - - - - Use the [`pay-for-service`](https://docs.cdp.coinbase.com/agentic-wallet/skills/pay-for-service) skill: - - ```bash Terminal - npx awal@latest x402 pay "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd" - ``` - - - ```bash Terminal - curl -X POST "https://api.wallet.paysponge.com/api/x402/fetch" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" \ - -H "Content-Type: application/json" \ - -d '{ - "url": "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd", - "method": "GET", - "preferred_chain": "base" - }' - ``` - - - -### Alchemy — onchain data - -Alchemy exposes enhanced APIs for onchain data — token balances, NFT metadata, mempool visibility, and decoded transaction history — via their [Agentic Gateway](https://github.com/alchemyplatform/skills/tree/main/skills/agentic-gateway) at `https://x402.alchemy.com`. - - - Alchemy's x402 gateway uses SIWE wallet authentication via their own [`@alchemy/x402`](https://github.com/alchemyplatform/skills/tree/main/skills/agentic-gateway) CLI — not a generic x402 bazaar endpoint. Follow the setup steps below before making requests. - - -**Step 1 — Install and set up a wallet:** - -```bash Terminal -npx @alchemy/x402 wallet generate -``` - -**Step 2 — Generate a SIWE auth token:** - -```bash Terminal -npx @alchemy/x402 sign --private-key ./wallet-key.txt > siwe-token.txt -``` - -**Step 3 — Fetch token balances on Base:** - - - - ```bash Terminal - TOKEN=$(cat siwe-token.txt) - - curl -s -X POST "https://x402.alchemy.com/base-mainnet/v2" \ - -H "Content-Type: application/json" \ - -H "Authorization: SIWE $TOKEN" \ - -d '{ - "jsonrpc": "2.0", - "id": 1, - "method": "alchemy_getTokenBalances", - "params": ["0xYourAddress"] - }' - ``` - - - ```bash Terminal - TOKEN=$(cat siwe-token.txt) - - curl -s -X POST "https://x402.alchemy.com/data/v1/assets/tokens/by-address" \ - -H "Content-Type: application/json" \ - -H "Authorization: SIWE $TOKEN" \ - -d '{"addresses": ["0xYourAddress"], "withMetadata": true}' - ``` - - - ```bash Terminal - TOKEN=$(cat siwe-token.txt) - - curl -s -G "https://x402.alchemy.com/prices/v1/tokens/by-symbol" \ - --data-urlencode "symbols=ETH" \ - --data-urlencode "symbols=USDC" \ - -H "Authorization: SIWE $TOKEN" - ``` - - - -If the gateway returns `402`, handle payment with the CLI and retry: - -```bash Terminal -PAYMENT_SIG=$(npx @alchemy/x402 pay --private-key ./wallet-key.txt --payment-required "$PAYMENT_REQUIRED") -``` - -See the full [Alchemy Agentic Gateway skill](https://github.com/alchemyplatform/skills/tree/main/skills/agentic-gateway) for wallet bootstrap, payment handling, and SDK integration. - -## Making data calls inside an OpenClaw agent - -Install the [Sponge Wallet](https://www.paysponge.com) skill or [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/) skills, then prompt your agent directly: - -```text -Get the current prices of ETH, BTC, and SOL from a paid data source -``` - -```text -Check the token balances at 0xYourWatchAddress on Base -``` - -The agent handles service discovery, payment, and data extraction. For a custom implementation using `x402-axios`: - -```bash Terminal -npm install x402-axios axios -``` - -```typescript TypeScript -import { withPaymentInterceptor } from "x402-axios"; -import axios from "axios"; - -// walletClient must be a viem-compatible WalletClient -const client = withPaymentInterceptor(axios.create(), walletClient); - -// If the endpoint returns 402, the interceptor pays automatically and retries -const response = await client.get("https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd"); -console.log(response.data); -``` - -The interceptor handles the full 402 → pay → retry flow. For wiring a viem `WalletClient` to your setup, see the [x402 client docs](https://docs.cdp.coinbase.com/x402/docs/client-server-model). - -## Related - - - - Execute swaps using Flashblocks timing and Base fee calibration. - - - - Full x402 flow, supported networks, and error handling. - - diff --git a/docs/ai-agents/trading/trade-execution.mdx b/docs/ai-agents/trading/trade-execution.mdx deleted file mode 100644 index 6d5675bea..000000000 --- a/docs/ai-agents/trading/trade-execution.mdx +++ /dev/null @@ -1,115 +0,0 @@ ---- -title: "Trade Execution on Base" -description: "Base-specific patterns, fee calibration, and onchain signals for trading agents" -keywords: ["Flashblocks trading", "trading agent Base", "base_transactionStatus", "onchain trading agent EVM", "L1 L2 fee optimization Base", "token swap agent"] ---- - -import { TradeExecutionDemo } from "/snippets/TradeExecutionDemo.jsx" - -Base offers two structural advantages for trading agents: **Flashblocks** (200ms preconfirmed block state, 10× faster than the 2-second block) and an exposed L1/L2 fee structure that enables explicit cost-vs-speed tradeoffs. This page covers only what is unique to Base — general EVM execution patterns are in the [Ethereum documentation](https://ethereum.org/developers/docs), and Base's RPC methods are in the [API Reference](/base-chain/api-reference/rpc-overview). - -## Mock Demo - - - -## Executing swaps with wallet-native tools - -[Bankr](https://bankr.bot), [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/), and [Sponge Wallet](https://www.paysponge.com) all include built-in swap capabilities — no external DEX integration needed. - -With [Bankr](https://bankr.bot): - -```text -Buy $50 of ETH on Base -Swap 100 USDC for ETH at market price -``` - -With [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/) skills: - -```text -Buy $50 of ETH -Trade 0.01 ETH for USDC -``` - -With [Sponge Wallet](https://www.paysponge.com): - -```bash Terminal -curl -X POST "https://api.wallet.paysponge.com/api/swap" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" \ - -H "Content-Type: application/json" \ - -d '{ - "fromToken": "USDC", - "toToken": "ETH", - "amount": "100", - "chain": "base" - }' -``` - -## Execution patterns - -### Use the preconf endpoint for all reads and submissions - -Always connect to `mainnet-preconf.base.org` (or `sepolia-preconf.base.org` for testnet) rather than the standard endpoint. This is the only way to access Flashblocks `pending` state, preconfirmed transaction streams, and `base_transactionStatus`. See [Flashblocks endpoints](/base-chain/flashblocks/app-integration#rpc-endpoints) for the full list. - -### Simulate against preconfirmed state before signing - -Call [`eth_simulateV1`](/base-chain/api-reference/flashblocks-api/eth_simulateV1) against the preconf endpoint with `"blockStateCalls"` targeting the `pending` block before signing any transaction. This catches reverts against current Flashblocks state rather than the last sealed block — which may be up to 2 seconds stale by the time your transaction lands. - -### Poll `base_transactionStatus` instead of blocking on a receipt - -After submission, [`base_transactionStatus`](/base-chain/api-reference/flashblocks-api/base_transactionStatus) returns preconfirmed inclusion status within a single Flashblock interval (~200ms). Blocking on `eth_getTransactionReceipt` waits for a full sealed block (up to 2 seconds). For latency-sensitive strategies, poll `base_transactionStatus` first and only fall back to the receipt for finality confirmation. - -## Fee calibration - -### L2 priority fee heuristics - -Use [`eth_feeHistory`](/base-chain/api-reference/rpc-overview#eth_feehistory) over the last 5–10 blocks with reward percentiles `[50, 90]`: - -- **50th percentile reward** — standard inclusion within 1–3 Flashblocks -- **90th percentile reward** — fast inclusion within the next Flashblock -- **`maxFeePerGas`** — set to `nextBaseFee * 2 + maxPriorityFeePerGas` to survive base fee increases across multiple blocks without overpaying - -### L1 fee decision rule - -Before signing, estimate the L1 cost via the [GasPriceOracle](/base-chain/network-information/network-fees#querying-the-l1-fee). If the ratio below exceeds `0.8` and trade size is small, the L1 fee dominates total cost — consider deferring until Ethereum congestion subsides: - -``` -l1FeeUpperBound / (gasLimit × maxFeePerGas + l1FeeUpperBound) > 0.8 -``` - -## Base-specific failure modes - -Most transaction errors are standard EVM. These are the Base-specific cases that require different handling: - -| Failure | What it means | What to do | -| ------- | ------------- | ---------- | -| `replacement transaction underpriced` | Replacing a pending tx requires ≥10% higher `maxFeePerGas` **and** `maxPriorityFeePerGas` | Increase both by ≥10%, resubmit with same nonce | -| DA throttling (no error code returned) | Sequencer is rate-limiting L2 throughput to manage L1 data availability costs | Fee-bumping does not resolve this — wait for the throttle to lift | - -For the full error taxonomy, see [Troubleshooting Transactions](/base-chain/network-information/troubleshooting-transactions). - -**Nonce for concurrent submissions:** Always fetch with `eth_getTransactionCount(address, "pending")`. For parallel submissions, fetch once and increment locally — fetching fresh per call returns the same value for all concurrent requests. - -## Strategy signals - -Base exposes data that most chains don't provide at this resolution: - -| Signal | How to access | Opportunity category | -| ------ | ------------- | -------------------- | -| Preconfirmed pending block state (200ms early) | `eth_getBlockByNumber("pending")` on preconf endpoint | Detect price impact before block seals | -| Preconfirmed transaction stream | `eth_subscribe("newFlashblockTransactions")` | First-mover on large trades entering the block | -| Preconfirmed logs | `eth_subscribe("pendingLogs", { address, topics })` | Detect liquidation thresholds, oracle updates before finality | -| Fee spike detection | `eth_feeHistory` trend over last 5 blocks | Identify congestion onset; adjust routing or pause | -| L1 base fee trend | `GasPriceOracle.l1BaseFee()` polled over time | Time submissions to minimize L1 data cost | -| Block gas utilization | `gasUsedRatio` from `eth_feeHistory` | Predict upcoming base fee increases | - -**The Flashblocks advantage:** Most chains expose a pool of pending transactions with uncertain ordering. On Base, the Flashblocks endpoint gives agents a deterministic, ordered view of the next 200ms of chain state before it finalizes. This is an information edge that does not exist on chains with mempool-only visibility. - -## Related - -- [Flashblocks API Reference](/base-chain/api-reference/rpc-overview#flashblocks-api) — `eth_simulateV1`, `base_transactionStatus`, subscription types -- [Flashblocks Integration Guide](/base-chain/flashblocks/app-integration) — endpoints, library setup (Wagmi, Viem, Ethers) -- [Block Building](/base-chain/network-information/block-building) — Flashblocks timing, per-transaction gas maximum -- [Network Fees](/base-chain/network-information/network-fees) — EIP-1559 parameters, GasPriceOracle methods -- [JSON-RPC API Reference](/base-chain/api-reference/rpc-overview) — complete RPC method reference -- [Troubleshooting Transactions](/base-chain/network-information/troubleshooting-transactions) — full error taxonomy and retry policies diff --git a/docs/docs.json b/docs/docs.json index 241800d27..bddf6d58f 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -680,32 +680,35 @@ }, { "group": "Quickstart", - "pages": [ - "ai-agents/quickstart/payments", - "ai-agents/quickstart/trading" - ] + "pages": ["ai-agents/quickstart"] }, { "group": "Setup", "pages": [ - "ai-agents/setup/wallet-setup", - "ai-agents/setup/agent-builder-codes", - "ai-agents/setup/agent-registration" + "ai-agents/setup/index", + "ai-agents/setup/agent-builder-codes" ] }, { - "group": "Payments", + "group": "Guides", "pages": [ - "ai-agents/payments/pay-for-services-with-x402", - "ai-agents/payments/accepting-payments" + "ai-agents/guides/index", + "ai-agents/guides/check-balance", + "ai-agents/guides/send-tokens", + "ai-agents/guides/swap-tokens", + "ai-agents/guides/pay-for-services", + "ai-agents/guides/view-history", + "ai-agents/guides/sign-messages", + "ai-agents/guides/batch-calls" ] }, { - "group": "Trading", - "pages": [ - "ai-agents/trading/data-fetching", - "ai-agents/trading/trade-execution" - ] + "group": "Plugins", + "pages": ["ai-agents/plugins/morpho"] + }, + { + "group": "Payments", + "pages": ["ai-agents/payments"] }, { "group": "Skills", @@ -714,24 +717,13 @@ { "group": "Wallets", "pages": [ - "ai-agents/skills/wallets/bankr", - "ai-agents/skills/wallets/cdp-agentic-wallet", - "ai-agents/skills/wallets/sponge-wallet" + "ai-agents/skills/wallets/cdp-agentic-wallet" ] }, { "group": "Payments", "pages": [ - "ai-agents/skills/payments/cdp-payment-skills", - "ai-agents/skills/payments/sponge-x402" - ] - }, - { - "group": "Trading", - "pages": [ - "ai-agents/skills/trading/coingecko", - "ai-agents/skills/trading/alchemy-agentic-gateway", - "ai-agents/skills/trading/swap-execution" + "ai-agents/skills/payments/cdp-payment-skills" ] } ] @@ -799,7 +791,70 @@ ] }, "redirects": [ - + { + "source": "/ai-agents/quickstart/payments", + "destination": "/ai-agents/quickstart" + }, + { + "source": "/ai-agents/quickstart/trading", + "destination": "/ai-agents/quickstart" + }, + { + "source": "/ai-agents/setup/wallet-setup", + "destination": "/ai-agents/setup" + }, + { + "source": "/ai-agents/setup/agent-registration", + "destination": "/ai-agents/index" + }, + { + "source": "/ai-agents/payments/pay-for-services-with-x402", + "destination": "/ai-agents/payments" + }, + { + "source": "/ai-agents/payments/accepting-payments", + "destination": "/ai-agents/payments" + }, + { + "source": "/ai-agents/tools", + "destination": "/ai-agents/guides" + }, + { + "source": "/ai-agents/tools/index", + "destination": "/ai-agents/guides" + }, + { + "source": "/ai-agents/trading/data-fetching", + "destination": "/ai-agents/guides" + }, + { + "source": "/ai-agents/trading/trade-execution", + "destination": "/ai-agents/guides" + }, + { + "source": "/ai-agents/skills/wallets/bankr", + "destination": "/ai-agents/tools" + }, + { + "source": "/ai-agents/skills/wallets/sponge-wallet", + "destination": "/ai-agents/tools" + }, + { + "source": "/ai-agents/skills/payments/sponge-x402", + "destination": "/ai-agents/payments" + }, + { + "source": "/ai-agents/skills/trading/coingecko", + "destination": "/ai-agents/tools" + }, + { + "source": "/ai-agents/skills/trading/alchemy-agentic-gateway", + "destination": "/ai-agents/tools" + }, + { + "source": "/ai-agents/skills/trading/swap-execution", + "destination": "/ai-agents/tools" + }, { "source": "/base-chain/reference/json-rpc-api", "destination": "/base-chain/api-reference/rpc-overview" diff --git a/docs/snippets/AcceptingPaymentsDemo.jsx b/docs/snippets/AcceptingPaymentsDemo.jsx index 99ca4b529..416ec8129 100644 --- a/docs/snippets/AcceptingPaymentsDemo.jsx +++ b/docs/snippets/AcceptingPaymentsDemo.jsx @@ -1,5 +1,6 @@ import { useState, useEffect, useRef } from "react"; +// Morpho plugin orchestration demo — used in plugins/morpho.mdx export const AcceptingPaymentsDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; const col = { @@ -8,41 +9,50 @@ export const AcceptingPaymentsDemo = () => { active: "#60a5fa", success: "#34d399", code: "#d4d4d8", + warn: "#fb923c", }; const steps = [ - { delay: 350, left: [{ t: "> npm install x402-express express", c: "active" }], right: [ - { t: "── Middleware Config ───────────────────", c: "dim" }, - { t: "{", c: "code" }, + { delay: 400, left: [{ t: "> Find the best USDC vault on Base and deposit 100 USDC", c: "active" }], right: [ + { t: "── morpho_query_vaults ──────────────────", c: "dim" }, + { t: " asset: USDC", c: "muted" }, + { t: " sortBy: APY", c: "muted" }, + ]}, + { delay: 700, left: [{ t: " ← top vault: Morpho Flagship USDC", c: "muted" }], right: [ + { t: "", c: "dim" }, + { t: " Morpho Flagship USDC", c: "success" }, + { t: " APY: 8.42% TVL: $42.1M", c: "success" }, + { t: " address: 0x8eB6...4Fa1", c: "code" }, ]}, - { delay: 650, left: [{ t: " ✓ x402-express installed", c: "success" }], right: [ - { t: ' "path": "/api/data",', c: "code" }, - { t: ' "price": "$0.01",', c: "code" }, - { t: ' "network": "base",', c: "code" }, - { t: ' "payTo": "0x742d...c4f2"', c: "code" }, + { delay: 500, left: [{ t: "> prepare_deposit(vault, 100 USDC)", c: "active" }], right: [ + { t: "", c: "dim" }, + { t: "── morpho_prepare_deposit ───────────────", c: "dim" }, + { t: " Simulating deposit...", c: "muted" }, + ]}, + { delay: 700, left: [{ t: " ← simulation ok · calls ready", c: "muted" }], right: [ + { t: "", c: "dim" }, + { t: "{", c: "code" }, + { t: ' "chainId": "0x2105",', c: "code" }, + { t: ' "calls": [approve, deposit]', c: "code" }, { t: "}", c: "code" }, ]}, - { delay: 500, left: [{ t: "> configure x402 middleware...", c: "active" }], right: [] }, - { delay: 600, left: [{ t: " ✓ paymentMiddleware applied", c: "success" }], right: [] }, - { delay: 400, left: [{ t: " ✓ endpoint live: /api/data · $0.01/req", c: "success" }], right: [ + { delay: 500, left: [{ t: "> send_calls(chainId, calls)", c: "active" }], right: [ { t: "", c: "dim" }, - { t: "── Live endpoint ───────────────────────", c: "dim" }, - { t: " GET /api/data → 402 (unpaid)", c: "muted" }, - { t: " GET /api/data + sig → 200 (paid)", c: "success" }, + { t: "── send_calls ──────────────────────────", c: "dim" }, + { t: " Submitting to Base Account MCP...", c: "muted" }, ]}, - { delay: 900, left: [{ t: " waiting for requests...", c: "muted" }], right: [ + { delay: 600, left: [{ t: " ← approval required", c: "warn" }], right: [ { t: "", c: "dim" }, - { t: "── Incoming request ────────────────────", c: "dim" }, - { t: "GET /api/data", c: "code" }, - { t: "X-Payment-Sig: 0xc3d1...f891", c: "success" }, + { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, + { t: ' requestId: "req_xyz789"', c: "muted" }, ]}, - { delay: 700, left: [{ t: " ← payment verified · 0.01 USDC", c: "muted" }], right: [ + { delay: 500, left: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }], right: [] }, + { delay: 1000, left: [{ t: " ← user approved ✓", c: "success" }], right: [ { t: "", c: "dim" }, - { t: "── Payment verified ────────────────────", c: "dim" }, - { t: " amount: 0.01 USDC ✓", c: "success" }, - { t: " sig valid: true ✓", c: "success" }, + { t: "── get_request_status ──────────────────", c: "dim" }, + { t: ' status: "confirmed"', c: "success" }, ]}, - { delay: 400, left: [{ t: " ✓ serving data · balance +0.01 USDC", c: "success", bold: true }], right: [] }, + { delay: 400, left: [{ t: " ✓ 100 USDC deposited · earning 8.42% APY", c: "success" }], right: [] }, ]; const [leftLines, setLeftLines] = useState([]); @@ -53,39 +63,31 @@ export const AcceptingPaymentsDemo = () => { const leftRef = useRef(null); const rightRef = useRef(null); - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); - + useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); + useEffect(() => { if (rightRef.current) rightRef.current.scrollTop = rightRef.current.scrollHeight; }, [rightLines]); + + const reset = () => { setLeftLines([]); setRightLines([]); setRunning(false); setDone(false); }; - const play = () => { - setLeftLines([]); - setRightLines([]); + const run = () => { + if (running || done) return; setRunning(true); - setDone(false); let i = 0; const next = () => { if (i >= steps.length) { setRunning(false); setDone(true); return; } const s = steps[i]; setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); + if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); + i++; next(); }, s.delay); }; next(); }; - useEffect(() => { setTimeout(play, 350); }, []); // eslint-disable-line react-hooks/exhaustive-deps - const renderLine = (item, i) => { if (!item.t) return
; - return ( -
{item.t}
- ); + return
{item.t}
; }; return ( @@ -94,33 +96,41 @@ export const AcceptingPaymentsDemo = () => {
{">"}_
- Accepting Payments + Morpho + Base Account MCP
- + onMouseLeave={e => { e.currentTarget.style.color = "#3f3f46"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "transparent"; }}>{"↺"}
- -
-
- Agent +
+
+
+ Agent +
+
+ {leftLines.map(renderLine)} + {running &&
{"▋"}
} +
-
- {leftLines.map(renderLine)} - {running &&
{"▋"}
} +
+
+ MCP Response +
+
+ {rightLines.map(renderLine)} +
-
+ {!running && !done && leftLines.length === 0 && ( + + )} {done && ( - + onMouseLeave={e => { e.currentTarget.style.color = "#52525b"; e.currentTarget.style.background = "none"; }}>{"↺"} Play again )}
diff --git a/docs/snippets/AgentPaymentDemo.jsx b/docs/snippets/AgentPaymentDemo.jsx index 5224d02e1..a21b0772b 100644 --- a/docs/snippets/AgentPaymentDemo.jsx +++ b/docs/snippets/AgentPaymentDemo.jsx @@ -8,199 +8,158 @@ export const AgentPaymentDemo = () => { active: "#60a5fa", success: "#34d399", code: "#d4d4d8", + warn: "#fb923c", }; const flows = { - wallet_cdp: [ - { delay: 350, left: [{ t: "> npx skills add coinbase/agentic-wallet-skills", c: "active" }], right: [ - { t: "── wallet.config.json ──────────────────", c: "dim" }, + // Tab 0 — Connect: platform choice + connect_claude: [ + { delay: 400, left: [{ t: "> claude mcp add --transport http base-account https://mcp.base.org", c: "active" }], right: [ + { t: "── .claude/settings.json ───────────────", c: "dim" }, { t: "{", c: "code" }, ]}, - { delay: 550, left: [{ t: " ✓ skill installed", c: "success" }], right: [ - { t: ' "provider": "coinbase",', c: "code" }, - { t: ' "network": "base",', c: "code" }, - { t: ' "skills": ["agentic-wallet"]', c: "code" }, + { delay: 650, left: [{ t: " ✓ MCP server added: base-account", c: "success" }], right: [ + { t: ' "mcpServers": {', c: "code" }, + { t: ' "base-account": {', c: "code" }, + { t: ' "url": "https://mcp.base.org"', c: "code" }, + { t: " }", c: "code" }, + { t: " }", c: "code" }, { t: "}", c: "code" }, ]}, - { delay: 500, left: [{ t: "> Sign in with your@email.com", c: "active" }], right: [] }, - { delay: 650, left: [{ t: " ← OTP sent · checking...", c: "muted" }], right: [] }, - { delay: 600, left: [{ t: " ✓ CDP wallet connected 0x4a3f...b7c1", c: "success" }], right: [ + { delay: 600, left: [{ t: "> Show me my wallets", c: "active" }], right: [] }, + { delay: 500, left: [{ t: " ← Authorizing via keys.coinbase.com...", c: "warn" }], right: [ { t: "", c: "dim" }, - { t: " address: 0x4a3f...b7c1", c: "success" }, - { t: " network: base-mainnet", c: "success" }, + { t: "── OAuth ───────────────────────────────", c: "dim" }, + { t: " → keys.coinbase.com/authorize", c: "warn" }, ]}, - ], - wallet_sponge: [ - { delay: 350, left: [{ t: "> curl -X POST https://api.wallet.paysponge.com/...", c: "active" }], right: [ - { t: "── POST /api/agents/register ───────────", c: "dim" }, - { t: "Host: api.wallet.paysponge.com", c: "muted" }, - { t: "Content-Type: application/json", c: "muted" }, - ]}, - { delay: 750, left: [{ t: ' ← {"apiKey": "sponge_live_..."}', c: "muted" }], right: [ + { delay: 800, left: [{ t: " ✓ Base Account connected 0x4a3f...b7c1", c: "success" }], right: [ { t: "", c: "dim" }, - { t: "── 200 OK ──────────────────────────────", c: "dim" }, - { t: "{", c: "code" }, - { t: ' "apiKey": "sponge_live_abc...xyz",', c: "code" }, - { t: ' "walletId": "wlt_a1b2c3d4"', c: "code" }, - { t: "}", c: "code" }, + { t: ' address: "0x4a3f...b7c1"', c: "success" }, + { t: ' network: "base-mainnet"', c: "success" }, + { t: ' status: "ready"', c: "success" }, ]}, - { delay: 450, left: [{ t: "> export SPONGE_API_KEY=sponge_live_...", c: "active" }], right: [] }, - { delay: 450, left: [{ t: " ✓ Sponge wallet ready", c: "success" }], right: [] }, ], - wallet_bankr: [ - { delay: 350, left: [{ t: "> install bankr skill from github.com/BankrBot/skills", c: "active" }], right: [ - { t: "── github.com/BankrBot/skills ──────────", c: "dim" }, - { t: "GET /releases/latest", c: "muted" }, + connect_desktop: [ + { delay: 400, left: [{ t: "> Edit claude_desktop_config.json", c: "active" }], right: [ + { t: "── claude_desktop_config.json ──────────", c: "dim" }, + { t: "{", c: "code" }, ]}, - { delay: 700, left: [{ t: " ✓ Bankr skill installed", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: " tag: bankr-wallet-v2.1.0", c: "success" }, - { t: " size: 142 KB", c: "muted" }, + { delay: 600, left: [{ t: " Adding base-account entry...", c: "muted" }], right: [ + { t: ' "mcpServers": {', c: "code" }, + { t: ' "base-account": {', c: "code" }, + { t: ' "url": "https://mcp.base.org"', c: "code" }, + { t: " }", c: "code" }, + { t: " }", c: "code" }, + { t: "}", c: "code" }, ]}, - { delay: 500, left: [{ t: " ✓ Bankr wallet connected", c: "success" }], right: [ - { t: " ready: true", c: "success" }, + { delay: 550, left: [{ t: " Restart Claude Desktop →", c: "muted" }], right: [] }, + { delay: 700, left: [{ t: " ✓ base-account MCP connected", c: "success" }], right: [ + { t: "", c: "dim" }, + { t: "── toolbar ─────────────────────────────", c: "dim" }, + { t: " [🔵 base-account] connected", c: "success" }, ]}, ], - pay: [ - { delay: 350, left: [{ t: "> Find and fetch ETH price from a paid source", c: "active" }], right: [ - { t: "── Request ─────────────────────────────", c: "dim" }, - { t: "GET /api/v3/simple/price?ids=ethereum", c: "code" }, - { t: "Host: api.coingecko.com", c: "muted" }, + connect_chatgpt: [ + { delay: 400, left: [{ t: "> Settings → Connectors → Add MCP", c: "active" }], right: [ + { t: "── ChatGPT Connectors ───────────────────", c: "dim" }, + { t: " Add custom connector", c: "muted" }, ]}, - { delay: 600, left: [{ t: " → GET api.coingecko.com/simple/price", c: "muted" }], right: [] }, - { delay: 650, left: [{ t: " ← 402 Payment Required · 0.001 USDC", c: "muted" }], right: [ + { delay: 550, left: [{ t: " Enter: https://mcp.base.org", c: "muted" }], right: [ { t: "", c: "dim" }, - { t: "── Response 1 ──────────────────────────", c: "dim" }, - { t: "HTTP/1.1 402 Payment Required", c: "muted" }, - { t: 'X-Payment-Required: {', c: "muted" }, - { t: ' "amount": "0.001", "asset": "USDC"', c: "code" }, - { t: '}', c: "muted" }, + { t: " Server URL:", c: "muted" }, + { t: " https://mcp.base.org [Save]", c: "active" }, ]}, - { delay: 650, left: [{ t: " paying via wallet...", c: "muted" }], right: [] }, - { delay: 600, left: [{ t: " ✓ tx confirmed", c: "success" }], right: [] }, - { delay: 500, left: [{ t: " → retrying with payment signature", c: "muted" }], right: [ + { delay: 700, left: [{ t: " ✓ Base Account MCP saved", c: "success" }], right: [ { t: "", c: "dim" }, - { t: "── Request 2 ───────────────────────────", c: "dim" }, - { t: "GET /api/v3/simple/price?ids=ethereum", c: "code" }, - { t: "X-Payment-Sig: 0x1a9f...c4e2", c: "success" }, + { t: "── Connectors ──────────────────────────", c: "dim" }, + { t: " ✓ base-account mcp.base.org", c: "success" }, ]}, - { delay: 600, left: [{ t: " ← 200 OK", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── Response 2 ──────────────────────────", c: "dim" }, - { t: "HTTP/1.1 200 OK", c: "success" }, - { t: '{"ethereum":{"usd":2847.32}}', c: "code" }, - ]}, - { delay: 300, left: [{ t: " ETH $2,847.32 ↑ 2.3%", c: "code", bold: true }], right: [] }, ], - getpaid: [ - { delay: 350, left: [{ t: "> Set up a paid endpoint at $0.01 per request", c: "active" }], right: [ - { t: "── x402 middleware config ──────────────", c: "dim" }, - { t: "{", c: "code" }, - { t: ' "path": "/market-data",', c: "code" }, - { t: ' "price": "0.01",', c: "code" }, - { t: ' "asset": "USDC"', c: "code" }, - { t: "}", c: "code" }, - ]}, - { delay: 600, left: [{ t: " creating x402 middleware...", c: "muted" }], right: [] }, - { delay: 500, left: [{ t: " ✓ endpoint live: api.myagent.com/market-data", c: "success" }], right: [] }, - { delay: 400, left: [{ t: " ✓ payTo: 0x742d...c4f2", c: "success" }], right: [] }, - { delay: 800, left: [{ t: " waiting for requests...", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "── Incoming request ────────────────────", c: "dim" }, - { t: "GET /market-data", c: "code" }, - { t: "X-Payment-Sig: 0xc3d1...f891", c: "success" }, + + // Tab 1 — Wallets & Balances: linear + balances: [ + { delay: 400, left: [{ t: "> Show me my wallets", c: "active" }], right: [ + { t: "── get_wallets ─────────────────────────", c: "dim" }, + { t: "tool: get_wallets()", c: "muted" }, ]}, - { delay: 700, left: [{ t: " ← incoming payment · 0.01 USDC", c: "muted" }], right: [ + { delay: 650, left: [{ t: " ← 2 wallets", c: "muted" }], right: [ { t: "", c: "dim" }, - { t: "── Payment verified ────────────────────", c: "dim" }, - { t: " amount: 0.01 USDC ✓", c: "success" }, - { t: " sig valid: true ✓", c: "success" }, + { t: ' { type: "base-account",', c: "code" }, + { t: ' address: "0x4a3f...b7c1",', c: "code" }, + { t: ' inSession: true }', c: "code" }, ]}, - { delay: 450, left: [{ t: " ✓ payment verified · serving data", c: "success" }], right: [] }, - ], - swap_cdp: [ - { delay: 350, left: [{ t: " ✓ using CDP wallet 0x4a3f...b7c1", c: "success" }], right: [ - { t: "── Swap quote ───────────────────────────", c: "dim" }, - { t: "POST /v1/swap/quote", c: "code" }, - { t: "Host: api.developer.coinbase.com", c: "muted" }, - ]}, - { delay: 500, left: [{ t: "> Buy $50 of ETH on Base", c: "active" }], right: [] }, - { delay: 600, left: [{ t: " fetching quote...", c: "muted" }], right: [ + { delay: 400, left: [{ t: " Base Account: 0x4a3f...b7c1", c: "success" }], right: [ { t: "", c: "dim" }, - { t: "── Quote response ───────────────────────", c: "dim" }, - { t: '{"fromAmount":"50.00 USDC",', c: "code" }, - { t: ' "toAmount":"0.01756 ETH",', c: "code" }, - { t: ' "priceImpact":"0.12%"}', c: "code" }, + { t: ' { type: "agent-wallet",', c: "code" }, + { t: ' address: "0x9c2d...e4f8",', c: "code" }, + { t: ' inSession: false }', c: "code" }, ]}, - { delay: 500, left: [{ t: " ← 0.01756 ETH · price impact 0.12%", c: "muted" }], right: [] }, - { delay: 550, left: [{ t: " impact below 1% — executing...", c: "muted" }], right: [] }, - { delay: 700, left: [{ t: " ✓ tx 0xb4f2...91ca confirmed", c: "success" }], right: [ + { delay: 600, left: [{ t: "> What's my balance on Base?", c: "active" }], right: [] }, + { delay: 500, left: [{ t: " ← get_portfolio(chain=base)", c: "muted" }], right: [ { t: "", c: "dim" }, - { t: "── Transaction ──────────────────────────", c: "dim" }, - { t: " hash: 0xb4f2...91ca", c: "success" }, - { t: " status: confirmed", c: "success" }, - { t: " block: 28,419,042", c: "muted" }, + { t: "── get_portfolio ────────────────────────", c: "dim" }, + { t: " USDC 245.80 $245.80", c: "success" }, + { t: " ETH 0.0412 $148.33", c: "success" }, + { t: " WETH 0.0100 $36.02 ", c: "success" }, ]}, - { delay: 400, left: [{ t: " ✓ received 0.01756 ETH", c: "success" }], right: [] }, + { delay: 400, left: [{ t: " Total: $430.15 on Base", c: "success" }], right: [] }, ], - swap_sponge: [ - { delay: 350, left: [{ t: " ✓ using Sponge wallet", c: "success" }], right: [ - { t: "── Swap quote ───────────────────────────", c: "dim" }, - { t: "POST /swap/quote", c: "code" }, - { t: "Host: api.wallet.paysponge.com", c: "muted" }, + + // Tab 2 — Send & Swap: choice + send: [ + { delay: 400, left: [{ t: "> Send 10 USDC to alice.base.eth", c: "active" }], right: [ + { t: "── send() ──────────────────────────────", c: "dim" }, + { t: " recipient: alice.base.eth", c: "muted" }, + { t: " amount: 10", c: "muted" }, + { t: " asset: USDC", c: "muted" }, + { t: " chain: base", c: "muted" }, ]}, - { delay: 500, left: [{ t: "> Buy $50 of ETH on Base", c: "active" }], right: [] }, - { delay: 600, left: [{ t: " fetching quote...", c: "muted" }], right: [ + { delay: 650, left: [{ t: " ← approval required", c: "warn" }], right: [ { t: "", c: "dim" }, - { t: "── Quote response ───────────────────────", c: "dim" }, - { t: '{"fromAmount":"50.00 USDC",', c: "code" }, - { t: ' "toAmount":"0.01756 ETH",', c: "code" }, - { t: ' "priceImpact":"0.12%"}', c: "code" }, + { t: "── approval mode ────────────────────────", c: "warn" }, + { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, + { t: ' requestId: "req_abc123"', c: "muted" }, ]}, - { delay: 500, left: [{ t: " ← 0.01756 ETH · price impact 0.12%", c: "muted" }], right: [] }, - { delay: 550, left: [{ t: " impact below 1% — executing...", c: "muted" }], right: [] }, - { delay: 700, left: [{ t: " ✓ tx 0xb4f2...91ca confirmed", c: "success" }], right: [ + { delay: 500, left: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }], right: [] }, + { delay: 900, left: [{ t: " ← user approved ✓", c: "success" }], right: [ { t: "", c: "dim" }, - { t: "── Transaction ──────────────────────────", c: "dim" }, - { t: " hash: 0xb4f2...91ca", c: "success" }, - { t: " status: confirmed", c: "success" }, - { t: " block: 28,419,042", c: "muted" }, + { t: "── get_request_status ──────────────────", c: "dim" }, + { t: ' status: "confirmed"', c: "success" }, + { t: ' txHash: "0xf7e3...9a12"', c: "success" }, ]}, - { delay: 400, left: [{ t: " ✓ received 0.01756 ETH", c: "success" }], right: [] }, + { delay: 400, left: [{ t: " ✓ 10 USDC sent to alice.base.eth", c: "success" }], right: [] }, ], - swap_bankr: [ - { delay: 350, left: [{ t: " ✓ using Bankr wallet", c: "success" }], right: [ - { t: "── Swap quote ───────────────────────────", c: "dim" }, - { t: "POST /swap/quote", c: "code" }, - { t: "Host: api.bankr.bot", c: "muted" }, + swap: [ + { delay: 400, left: [{ t: "> Swap 100 USDC for ETH on Base", c: "active" }], right: [ + { t: "── swap() ──────────────────────────────", c: "dim" }, + { t: " fromAsset: USDC", c: "muted" }, + { t: " toAsset: ETH", c: "muted" }, + { t: " amount: 100", c: "muted" }, + { t: " chain: base", c: "muted" }, ]}, - { delay: 500, left: [{ t: "> Buy $50 of ETH on Base", c: "active" }], right: [] }, - { delay: 600, left: [{ t: " fetching quote...", c: "muted" }], right: [ + { delay: 650, left: [{ t: " ← approval required", c: "warn" }], right: [ { t: "", c: "dim" }, - { t: "── Quote response ───────────────────────", c: "dim" }, - { t: '{"fromAmount":"50.00 USDC",', c: "code" }, - { t: ' "toAmount":"0.01756 ETH",', c: "code" }, - { t: ' "priceImpact":"0.12%"}', c: "code" }, + { t: "── approval mode ────────────────────────", c: "warn" }, + { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, + { t: ' requestId: "req_def456"', c: "muted" }, ]}, - { delay: 500, left: [{ t: " ← 0.01756 ETH · price impact 0.12%", c: "muted" }], right: [] }, - { delay: 550, left: [{ t: " impact below 1% — executing...", c: "muted" }], right: [] }, - { delay: 700, left: [{ t: " ✓ tx 0xb4f2...91ca confirmed", c: "success" }], right: [ + { delay: 500, left: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }], right: [] }, + { delay: 900, left: [{ t: " ← user approved ✓", c: "success" }], right: [ { t: "", c: "dim" }, - { t: "── Transaction ──────────────────────────", c: "dim" }, - { t: " hash: 0xb4f2...91ca", c: "success" }, - { t: " status: confirmed", c: "success" }, - { t: " block: 28,419,042", c: "muted" }, + { t: "── get_request_status ──────────────────", c: "dim" }, + { t: ' status: "confirmed"', c: "success" }, + { t: ' received: "0.03512 ETH"', c: "success" }, ]}, - { delay: 400, left: [{ t: " ✓ received 0.01756 ETH", c: "success" }], right: [] }, + { delay: 400, left: [{ t: " ✓ received 0.03512 ETH", c: "success" }], right: [] }, ], }; - const tabs = ["Setup Wallet", "Pay & Get Paid", "Swap"]; - const rightLabels = ["Wallet Config", "HTTP Trace", "Quote Details"]; + const tabs = ["Connect", "Wallets & Balances", "Send & Swap"]; + const rightLabels = ["Config", "MCP Response", "Approval Flow"]; const intros = [ - "> Setting up your agent wallet...", - "> Choose a flow:", - "> Which wallet should execute the swap?", + "> Choose your platform:", + "> Checking your Base Account...", + "> Choose an action:", ]; const [activeTab, setActiveTab] = useState(0); @@ -240,7 +199,13 @@ export const AgentPaymentDemo = () => { setChoice2(null); setRunning(false); setDone(false); - const t = setTimeout(() => setLeftLines([{ t: intros[activeTab], c: "muted" }]), 350); + const t = setTimeout(() => { + setLeftLines([{ t: intros[activeTab], c: "muted" }]); + // Tab 1 is linear — auto-start + if (activeTab === 1) { + setTimeout(() => animateFlow("balances"), 300); + } + }, 350); return () => clearTimeout(t); // eslint-disable-next-line react-hooks/exhaustive-deps }, [activeTab]); @@ -264,35 +229,27 @@ export const AgentPaymentDemo = () => { next(); }; - const pickWallet = (w) => { + const pickConnect = (p) => { if (choice1) return; - setChoice1(w); - setLeftLines(prev => [...prev, { t: " [" + w.toUpperCase() + "]", c: "active" }]); - setTimeout(() => animateFlow("wallet_" + w), 150); + setChoice1(p); + const labels = { claude: "Claude Code", desktop: "Claude Desktop", chatgpt: "ChatGPT" }; + setLeftLines(prev => [...prev, { t: " [" + labels[p] + "]", c: "active" }]); + setTimeout(() => animateFlow("connect_" + p), 150); }; - const pickPay = (p) => { + const pickAction = (a) => { if (choice2) return; - setChoice2(p); - const label = p === "pay" ? "Pay for a service" : "Get paid"; - setLeftLines(prev => [...prev, { t: " [" + label + "]", c: "active" }]); - setTimeout(() => animateFlow(p), 150); - }; - - const pickSwap = (w) => { - if (choice1) return; - setChoice1(w); - setLeftLines(prev => [...prev, { t: " [" + w.toUpperCase() + "]", c: "active" }]); - setTimeout(() => animateFlow("swap_" + w), 150); + setChoice2(a); + const labels = { send: "Send", swap: "Swap" }; + setLeftLines(prev => [...prev, { t: " [" + labels[a] + "]", c: "active" }]); + setTimeout(() => animateFlow(a), 150); }; const renderLine = (item, i) => { if (!item.t) return
; return (
{ cursor: "pointer", padding: "1px 8px", marginRight: 6, lineHeight: "20px", }; - const onBtnEnter = (e) => { - e.currentTarget.style.color = "#e4e4e7"; - e.currentTarget.style.background = "#1c1c1e"; - e.currentTarget.style.borderColor = "#3f3f46"; - }; - const onBtnLeave = (e) => { - e.currentTarget.style.color = "#60a5fa"; - e.currentTarget.style.background = "transparent"; - e.currentTarget.style.borderColor = "#27272a"; - }; + const onBtnEnter = (e) => { e.currentTarget.style.color = "#e4e4e7"; e.currentTarget.style.background = "#1c1c1e"; e.currentTarget.style.borderColor = "#3f3f46"; }; + const onBtnLeave = (e) => { e.currentTarget.style.color = "#60a5fa"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "#27272a"; }; - const showWalletBtns = activeTab === 0 && !choice1 && leftLines.length > 0; - const showPayBtns = activeTab === 1 && !choice2 && leftLines.length > 0; - const showSwapBtns = activeTab === 2 && !choice1 && leftLines.length > 0; - const isLastTab = activeTab === 2; - const footerLabel = isLastTab ? "\u21ba Play again" : "Next: " + tabs[activeTab + 1] + " \u2192"; + const showConnectBtns = activeTab === 0 && !choice1 && leftLines.length > 0; + const showActionBtns = activeTab === 2 && !choice2 && leftLines.length > 0; + const isLastTab = activeTab === 2; + const footerLabel = isLastTab ? "↺ Play again" : "Next: " + tabs[activeTab + 1] + " →"; return (
{/* Tab bar */}
- -
+
{">"}_
- {tabs.map((tab, i) => { const active = i === activeTab; return ( - ); })} -
- -
- {/* Terminal pane */} -
-
- Agent + {/* Split pane */} +
+ {/* Left — Agent */} +
+
+ Agent +
+
+ {leftLines.map(renderLine)} + {showConnectBtns && ( +
+ pick: + + + +
+ )} + {showActionBtns && ( +
+ pick: + + +
+ )} + {running &&
{"▋"}
} +
-
- {leftLines.map(renderLine)} - - {showWalletBtns && ( -
- pick: - - - -
- )} - {showPayBtns && ( -
- pick: - - -
- )} - {showSwapBtns && ( -
- pick: - - - -
- )} - - {running && ( -
{"▋"}
- )} + {/* Right — Config/Response */} +
+
+ {rightLabels[activeTab]} +
+
+ {rightLines.map(renderLine)} +
{/* Footer */}
{done && ( - )}
-
); }; diff --git a/docs/snippets/AgentRegistrationDemo.jsx b/docs/snippets/AgentRegistrationDemo.jsx index 9b83e2053..d62899ee4 100644 --- a/docs/snippets/AgentRegistrationDemo.jsx +++ b/docs/snippets/AgentRegistrationDemo.jsx @@ -2,85 +2,57 @@ import { useState, useEffect, useRef } from "react"; export const AgentRegistrationDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", - }; + const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8" }; const steps = [ - { delay: 400, left: [{ t: "> npm install @buildersgarden/siwa", c: "active" }], right: [ - { t: "── ERC-8004 Registry ───────────────────", c: "dim" }, - { t: "0x8004A169FB4...9f432", c: "muted" }, + { delay: 400, lines: [{ t: "> Show my last 5 transactions on Base", c: "active" }] }, + { delay: 500, lines: [ + { t: " ── get_transaction_history ────────────────", c: "dim" }, + { t: " chain: base limit: 5", c: "muted" }, ]}, - { delay: 700, left: [{ t: " ✓ @buildersgarden/siwa installed", c: "success" }], right: [] }, - { delay: 500, left: [{ t: "> Register agent identity onchain...", c: "active" }], right: [] }, - { delay: 800, left: [{ t: " signing registration tx...", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "── Registering ─────────────────────────", c: "dim" }, - { t: " name: my-trading-agent", c: "code" }, - { t: " endpoint: https://agent.example.com", c: "code" }, - { t: " pubKey: 0x04c2...f9a1", c: "code" }, + { delay: 700, lines: [ + { t: " send -10.00 USDC alice.base.eth 2min ago", c: "code" }, + { t: " swap -100.00 USDC +0.0351 ETH 1hr ago ", c: "code" }, + { t: " recv +50.00 USDC coinbase.com 3hr ago ", c: "success" }, + { t: " send -5.00 USDC bob.eth 1d ago ", c: "code" }, + { t: " recv +100.00 USDC 0x9f3a...2e01 2d ago ", c: "success" }, ]}, - { delay: 900, left: [{ t: " ✓ tx confirmed · token ID: 4219", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── Registry entry ──────────────────────", c: "dim" }, - { t: " tokenId: 4219", c: "success" }, - { t: " owner: 0x4a3f...b7c1", c: "success" }, - { t: " block: 28,419,042", c: "muted" }, + { delay: 500, lines: [{ t: "", c: "dim" }, { t: "> What's my current balance?", c: "active" }] }, + { delay: 500, lines: [ + { t: " ── get_portfolio ──────────────────────────", c: "dim" }, ]}, - { delay: 600, left: [{ t: "> Claim Basename: myagent.base.eth", c: "active" }], right: [] }, - { delay: 700, left: [{ t: " ✓ myagent.base.eth registered", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── Basename ────────────────────────────", c: "dim" }, - { t: " name: myagent.base.eth", c: "success" }, - { t: " address: 0x4a3f...b7c1", c: "success" }, + { delay: 650, lines: [ + { t: " USDC 280.80 $280.80", c: "success" }, + { t: " ETH 0.0763 $274.33", c: "success" }, + { t: " DEGEN 4820.00 $182.33", c: "success" }, + { t: " Total: $737.46 on Base", c: "success" }, ]}, ]; - const [leftLines, setLeftLines] = useState([]); - const [rightLines, setRightLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const leftRef = useRef(null); - const rightRef = useRef(null); - - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); + const [lines, setLines] = useState([]); + const [running, setRunning] = useState(false); + const [done, setDone] = useState(false); + const [blink, setBlink] = useState(true); + const ref = useRef(null); - useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); + useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); + useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]); - const play = () => { - setLeftLines([]); - setRightLines([]); + const reset = () => { setLines([]); setRunning(false); setDone(false); }; + const run = () => { + if (running || done) return; setRunning(true); - setDone(false); let i = 0; const next = () => { if (i >= steps.length) { setRunning(false); setDone(true); return; } - const s = steps[i]; - setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); - }, s.delay); + setTimeout(() => { setLines(p => [...p, ...steps[i].lines]); i++; next(); }, steps[i].delay); }; next(); }; - useEffect(() => { setTimeout(play, 350); }, []); // eslint-disable-line react-hooks/exhaustive-deps - const renderLine = (item, i) => { - if (!item.t) return
; - return ( -
{item.t}
- ); + if (!item.t) return
; + return
{item.t}
; }; return ( @@ -89,34 +61,22 @@ export const AgentRegistrationDemo = () => {
{">"}_
- Agent Registration + Transaction History
- + onMouseLeave={e => { e.currentTarget.style.color = "#3f3f46"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "transparent"; }}>{"↺"}
- -
-
- Agent -
-
- {leftLines.map(renderLine)} +
+
Terminal
+
+ {lines.map(renderLine)} {running &&
{"▋"}
}
-
- {done && ( - - )} + {!running && !done && } + {done && }
); diff --git a/docs/snippets/DataFetchingDemo.jsx b/docs/snippets/DataFetchingDemo.jsx index 36355f730..3853403fd 100644 --- a/docs/snippets/DataFetchingDemo.jsx +++ b/docs/snippets/DataFetchingDemo.jsx @@ -2,92 +2,86 @@ import { useState, useEffect, useRef } from "react"; export const DataFetchingDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", - }; + const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8" }; - const steps = [ - { delay: 350, left: [{ t: "> Discover price feed service...", c: "active" }], right: [ - { t: "── Service Discovery ───────────────────", c: "dim" }, - { t: "GET /api/discover?query=price+feed", c: "code" }, - { t: "Host: api.wallet.paysponge.com", c: "muted" }, - ]}, - { delay: 700, left: [{ t: " ← found: api.coingecko.com · 0.001 USDC", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: '{"id":"coingecko-price",', c: "code" }, - { t: ' "baseUrl":"api.coingecko.com",', c: "code" }, - { t: ' "price":"0.001 USDC/req"}', c: "code" }, - ]}, - { delay: 500, left: [{ t: "> Fetch ETH price...", c: "active" }], right: [ - { t: "", c: "dim" }, - { t: "── API Request ─────────────────────────", c: "dim" }, - { t: "GET /api/v3/simple/price?ids=ethereum", c: "code" }, - ]}, - { delay: 600, left: [{ t: " ← 402 · paying 0.001 USDC...", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "HTTP/1.1 402 Payment Required", c: "muted" }, - { t: "X-Payment-Sig: pending...", c: "muted" }, - ]}, - { delay: 700, left: [{ t: " ✓ payment sent · retrying...", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── API Response ────────────────────────", c: "dim" }, - { t: "HTTP/1.1 200 OK", c: "success" }, - ]}, - { delay: 500, left: [{ t: " ← 200 OK · data returned", c: "success" }], right: [ - { t: '{"ethereum":{', c: "code" }, - { t: ' "usd": 2847.32,', c: "code" }, - { t: ' "usd_24h_change": 2.31', c: "code" }, - { t: "} }", c: "code" }, - ]}, - { delay: 350, left: [{ t: " ETH $2,847.32 ↑ 2.3%", c: "code", bold: true }], right: [] }, - ]; + const flows = { + wallets: [ + { delay: 450, + left: [{ t: "> Show me my wallets", c: "active" }, { t: " ← get_wallets()", c: "muted" }], + right: [{ t: "── get_wallets ─────────────────────", c: "dim" }, { t: " (no params required)", c: "muted" }] }, + { delay: 700, + left: [{ t: " Base Account: 0x4a3f...b7c1 ✓", c: "success" }, { t: " Agent Wallet: 0x9c2d...e4f8 (not in session)", c: "muted" }], + right: [{ t: "", c: "dim" }, { t: ' { type: "base-account",', c: "code" }, { t: ' address: "0x4a3f...b7c1",', c: "code" }, { t: ' inSession: true }', c: "code" }] }, + { delay: 500, + left: [{ t: "", c: "dim" }, { t: " 2 wallets found", c: "success" }], + right: [{ t: "", c: "dim" }, { t: ' { type: "agent-wallet",', c: "code" }, { t: ' address: "0x9c2d...e4f8",', c: "code" }, { t: ' inSession: false }', c: "code" }] }, + ], + portfolio: [ + { delay: 450, + left: [{ t: "> What's my balance on Base?", c: "active" }, { t: " ← get_portfolio(chain=base)", c: "muted" }], + right: [{ t: "── get_portfolio ────────────────────", c: "dim" }, { t: " chain: base", c: "muted" }] }, + { delay: 700, + left: [{ t: " USDC 245.80 $245.80", c: "success" }, { t: " ETH 0.0412 $148.33", c: "success" }], + right: [{ t: "", c: "dim" }, { t: " totalValue: $430.15", c: "success" }, { t: " assetCount: 3", c: "code" }] }, + { delay: 500, + left: [{ t: " WETH 0.0100 $36.02", c: "success" }, { t: " Total: $430.15 on Base ✓", c: "success" }], + right: [{ t: "", c: "dim" }, { t: ' { symbol: "WETH",', c: "code" }, { t: ' balance: "0.0100",', c: "code" }, { t: ' usdValue: "$36.02" }', c: "code" }] }, + ], + history: [ + { delay: 450, + left: [{ t: "> Show my recent USDC sends", c: "active" }, { t: " ← get_transaction_history(asset=USDC, limit=4)", c: "muted" }], + right: [{ t: "── get_transaction_history ─────────", c: "dim" }, { t: " asset: USDC limit: 4", c: "muted" }] }, + { delay: 700, + left: [{ t: " send -10.00 USDC alice.base.eth", c: "code" }, { t: " recv +50.00 USDC coinbase.com ", c: "success" }], + right: [{ t: "", c: "dim" }, { t: " hasMore: true", c: "muted" }, { t: ' nextCursor: "cur_abc..."', c: "muted" }] }, + { delay: 500, + left: [{ t: " send -5.00 USDC bob.eth ", c: "code" }, { t: " recv +100.00 USDC 0x9f3a...2e01 ", c: "success" }], + right: [{ t: "", c: "dim" }, { t: " 4 USDC transactions returned", c: "success" }, { t: " More pages available", c: "muted" }] }, + ], + }; - const [leftLines, setLeftLines] = useState([]); - const [rightLines, setRightLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); + const [choice, setChoice] = useState(null); + const [leftLines, setLeft] = useState([{ t: "> Try a read tool:", c: "muted" }]); + const [rightLines, setRight]= useState([]); + const [running, setRunning] = useState(false); + const [done, setDone] = useState(false); + const [blink, setBlink] = useState(true); const leftRef = useRef(null); const rightRef = useRef(null); - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); - + useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); + useEffect(() => { if (rightRef.current) rightRef.current.scrollTop = rightRef.current.scrollHeight; }, [rightLines]); + + const reset = () => { setChoice(null); setLeft([{ t: "> Try a read tool:", c: "muted" }]); setRight([]); setRunning(false); setDone(false); }; - const play = () => { - setLeftLines([]); - setRightLines([]); + const pick = (key) => { + if (choice) return; + const labels = { wallets: "get_wallets", portfolio: "get_portfolio", history: "get_transaction_history" }; + setChoice(key); + setLeft(p => [...p, { t: " [" + labels[key] + "]", c: "active" }]); + const steps = flows[key]; setRunning(true); - setDone(false); let i = 0; const next = () => { if (i >= steps.length) { setRunning(false); setDone(true); return; } const s = steps[i]; setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); + if (s.left) setLeft(p => [...p, ...s.left]); + if (s.right) setRight(p => [...p, ...s.right]); + i++; next(); }, s.delay); }; - next(); + setTimeout(next, 200); }; - useEffect(() => { setTimeout(play, 350); }, []); // eslint-disable-line react-hooks/exhaustive-deps - const renderLine = (item, i) => { - if (!item.t) return
; - return ( -
{item.t}
- ); + if (!item.t) return
; + return
{item.t}
; }; + const btnBase = { fontFamily: mono, fontSize: 12, color: "#60a5fa", background: "transparent", border: "1px solid #27272a", borderRadius: 4, cursor: "pointer", padding: "2px 8px", marginRight: 6, lineHeight: "20px" }; + const onEnter = (e) => { e.currentTarget.style.color = "#e4e4e7"; e.currentTarget.style.background = "#1c1c1e"; e.currentTarget.style.borderColor = "#3f3f46"; }; + const onLeave = (e) => { e.currentTarget.style.color = "#60a5fa"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "#27272a"; }; return (
@@ -95,34 +89,34 @@ export const DataFetchingDemo = () => {
{">"}_
- Data Fetching + Read Tools
- + onMouseLeave={e => { e.currentTarget.style.color = "#3f3f46"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "transparent"; }}>{"↺"}
- -
-
- Agent +
+
+
Agent
+
+ {leftLines.map(renderLine)} + {!choice && ( +
+ + + +
+ )} + {running &&
{"▋"}
} +
-
- {leftLines.map(renderLine)} - {running &&
{"▋"}
} +
+
MCP Response
+
{rightLines.map(renderLine)}
-
- {done && ( - - )} + {done && }
); diff --git a/docs/snippets/PaymentsQuickstartDemo.jsx b/docs/snippets/PaymentsQuickstartDemo.jsx index 0b9050d56..05a33e902 100644 --- a/docs/snippets/PaymentsQuickstartDemo.jsx +++ b/docs/snippets/PaymentsQuickstartDemo.jsx @@ -1,5 +1,6 @@ import { useState, useEffect, useRef } from "react"; +// CDP x402 payments demo — used in payments.mdx export const PaymentsQuickstartDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; const col = { @@ -12,44 +13,40 @@ export const PaymentsQuickstartDemo = () => { const steps = [ { delay: 350, left: [{ t: "> npx skills add coinbase/agentic-wallet-skills", c: "active" }], right: [ - { t: "── Installing skills ───────────────────", c: "dim" }, + { t: "── Installing CDP skills ───────────────", c: "dim" }, { t: "authenticate-wallet", c: "muted" }, { t: "pay-for-service", c: "muted" }, - { t: "monetize-service", c: "muted" }, - ]}, - { delay: 700, left: [{ t: " ✓ skills installed", c: "success" }], right: [ { t: "search-for-service", c: "muted" }, - { t: "send-usdc trade", c: "muted" }, + { t: "monetize-service", c: "muted" }, ]}, + { delay: 700, left: [{ t: " ✓ CDP Agentic Wallet skills installed", c: "success" }], right: [] }, { delay: 500, left: [{ t: "> Sign in with you@email.com", c: "active" }], right: [] }, - { delay: 650, left: [{ t: " ✓ wallet authenticated 0x4a3f...b7c1", c: "success" }], right: [ + { delay: 650, left: [{ t: " ✓ CDP wallet authenticated 0x4a3f...b7c1", c: "success" }], right: [ { t: "", c: "dim" }, - { t: "── Wallet ready ────────────────────────", c: "dim" }, + { t: "── wallet ready ────────────────────────", c: "dim" }, { t: " address: 0x4a3f...b7c1", c: "success" }, { t: " balance: 10.00 USDC", c: "success" }, ]}, - { delay: 500, left: [{ t: "> Find and fetch ETH price from a paid source", c: "active" }], right: [ + { delay: 500, left: [{ t: "> Find a weather API and get the NYC forecast", c: "active" }], right: [ { t: "", c: "dim" }, - { t: "── HTTP Trace ──────────────────────────", c: "dim" }, - { t: "GET /api/v3/simple/price?ids=ethereum", c: "code" }, - { t: "Host: api.coingecko.com", c: "muted" }, + { t: "── search-for-service ──────────────────", c: "dim" }, + { t: 'query: "weather forecast"', c: "code" }, ]}, - { delay: 700, left: [{ t: " ← 402 Payment Required · 0.001 USDC", c: "muted" }], right: [ + { delay: 700, left: [{ t: " ← found: weather.x402.io · 0.001 USDC/req", c: "muted" }], right: [ { t: "", c: "dim" }, - { t: "HTTP/1.1 402 Payment Required", c: "muted" }, - { t: 'X-Payment-Required: {"amount":"0.001"}', c: "code" }, + { t: "── pay-for-service ─────────────────────", c: "dim" }, + { t: "GET /v1/forecast?city=NYC", c: "code" }, + { t: "← HTTP 402 Payment Required", c: "muted" }, ]}, - { delay: 550, left: [{ t: " paying 0.001 USDC via wallet...", c: "muted" }], right: [] }, - { delay: 600, left: [{ t: " ✓ tx confirmed", c: "success" }], right: [ + { delay: 550, left: [{ t: " paying 0.001 USDC...", c: "muted" }], right: [ { t: "", c: "dim" }, - { t: "── Retry with payment ──────────────────", c: "dim" }, - { t: "GET /api/v3/simple/price?ids=ethereum", c: "code" }, - { t: "X-Payment-Sig: 0x1a9f...c4e2", c: "success" }, + { t: " Paying 0.001 USDC · signing...", c: "muted" }, + { t: " Retrying with X-Payment-Sig", c: "muted" }, ]}, - { delay: 600, left: [{ t: " ← 200 OK · ETH $2,847.32 ↑ 2.3%", c: "success", bold: true }], right: [ + { delay: 600, left: [{ t: " ← 200 OK · forecast received", c: "success", bold: true }], right: [ { t: "", c: "dim" }, { t: "HTTP/1.1 200 OK", c: "success" }, - { t: '{"ethereum":{"usd":2847.32}}', c: "code" }, + { t: '{"city":"NYC","temp":"68°F",...}', c: "code" }, ]}, ]; @@ -67,6 +64,7 @@ export const PaymentsQuickstartDemo = () => { }, []); useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); + useEffect(() => { if (rightRef.current) rightRef.current.scrollTop = rightRef.current.scrollHeight; }, [rightLines]); const play = () => { setLeftLines([]); @@ -102,22 +100,32 @@ export const PaymentsQuickstartDemo = () => {
{">"}_
- Payments Quickstart + x402 via CDP Agentic Wallet
-
-
- Agent +
+
+
+ Agent +
+
+ {leftLines.map(renderLine)} + {running &&
{"▋"}
} +
-
- {leftLines.map(renderLine)} - {running &&
{"▋"}
} +
+
+ HTTP Trace +
+
+ {rightLines.map(renderLine)} +
@@ -127,7 +135,7 @@ export const PaymentsQuickstartDemo = () => { style={{ fontFamily: mono, fontSize: 11, color: "#52525b", background: "none", border: "none", cursor: "pointer", padding: "4px 10px", borderRadius: 4 }} onMouseEnter={e => { e.currentTarget.style.color = "#a1a1aa"; e.currentTarget.style.background = "#18181b"; }} onMouseLeave={e => { e.currentTarget.style.color = "#52525b"; e.currentTarget.style.background = "none"; }}> - {"\u21ba"} Play again + {"↺"} Play again )}
diff --git a/docs/snippets/TradeExecutionDemo.jsx b/docs/snippets/TradeExecutionDemo.jsx index 959b3898e..6fbc00fe8 100644 --- a/docs/snippets/TradeExecutionDemo.jsx +++ b/docs/snippets/TradeExecutionDemo.jsx @@ -2,97 +2,54 @@ import { useState, useEffect, useRef } from "react"; export const TradeExecutionDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", - }; + const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8", warn: "#fb923c" }; const steps = [ - { delay: 350, left: [{ t: "> Connect to mainnet-preconf.base.org...", c: "active" }], right: [ - { t: "── Flashblocks State ───────────────────", c: "dim" }, - { t: "eth_getBlockByNumber(\"pending\")", c: "code" }, - { t: "Host: mainnet-preconf.base.org", c: "muted" }, - ]}, - { delay: 650, left: [{ t: " ✓ preconf endpoint connected (200ms)", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: '{"pending": {', c: "code" }, - { t: ' "number": "0x1B2A4F2",', c: "code" }, - { t: ' "baseFeePerGas": "0x2386F26FC10"', c: "code" }, - { t: "} }", c: "code" }, + { delay: 400, lines: [{ t: "> Send 50 DEGEN to alice.base.eth", c: "active" }] }, + { delay: 500, lines: [ + { t: " ── search_tokens ──────────────────────────", c: "dim" }, + { t: ' query: "DEGEN" chain: base', c: "muted" }, ]}, - { delay: 500, left: [{ t: "> Simulate buying $50 ETH (preconf state)...", c: "active" }], right: [ - { t: "", c: "dim" }, - { t: "── eth_simulateV1 ──────────────────────", c: "dim" }, - { t: "blockStateCalls: [pending]", c: "muted" }, + { delay: 650, lines: [ + { t: ' ← name: "Degen" symbol: "DEGEN"', c: "code" }, + { t: ' address: "0x4ed4...9fa2" decimals: 18', c: "code" }, ]}, - { delay: 700, left: [{ t: " ✓ simulation passed · no revert", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: '{"results":[{"status":"0x1",', c: "code" }, - { t: ' "gasUsed":"0x14c08"}]}', c: "code" }, + { delay: 500, lines: [{ t: "", c: "dim" }, { t: "> send(alice.base.eth, 50 DEGEN, 0x4ed4..., 18)", c: "active" }] }, + { delay: 500, lines: [ + { t: " ── approval required ──────────────────────", c: "warn" }, + { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, ]}, - { delay: 450, left: [{ t: "> Get swap quote · price impact check...", c: "active" }], right: [ - { t: "", c: "dim" }, - { t: "── Quote Details ───────────────────────", c: "dim" }, - { t: '{"fromAmount":"50.00 USDC",', c: "code" }, - { t: ' "toAmount":"0.01756 ETH",', c: "code" }, - { t: ' "priceImpact":"0.12%"}', c: "code" }, + { delay: 500, lines: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }] }, + { delay: 1000, lines: [ + { t: ' ← status: "confirmed"', c: "success" }, + { t: " ✓ 50 DEGEN sent to alice.base.eth", c: "success" }, ]}, - { delay: 500, left: [{ t: " impact 0.12% < 1% — executing...", c: "muted" }], right: [] }, - { delay: 750, left: [{ t: " ✓ tx 0xb4f2...91ca confirmed (1 Flashblock)", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── base_transactionStatus ──────────────", c: "dim" }, - { t: " status: preconfirmed", c: "success" }, - { t: " hash: 0xb4f2...91ca", c: "success" }, - { t: " block: 28,419,042", c: "muted" }, - { t: " latency: ~200ms", c: "muted" }, - ]}, - { delay: 350, left: [{ t: " ✓ received 0.01756 ETH", c: "success", bold: true }], right: [] }, ]; - const [leftLines, setLeftLines] = useState([]); - const [rightLines, setRightLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const leftRef = useRef(null); - const rightRef = useRef(null); - - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); + const [lines, setLines] = useState([]); + const [running, setRunning] = useState(false); + const [done, setDone] = useState(false); + const [blink, setBlink] = useState(true); + const ref = useRef(null); - useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); + useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); + useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]); - const play = () => { - setLeftLines([]); - setRightLines([]); + const reset = () => { setLines([]); setRunning(false); setDone(false); }; + const run = () => { + if (running || done) return; setRunning(true); - setDone(false); let i = 0; const next = () => { if (i >= steps.length) { setRunning(false); setDone(true); return; } - const s = steps[i]; - setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); - }, s.delay); + setTimeout(() => { setLines(p => [...p, ...steps[i].lines]); i++; next(); }, steps[i].delay); }; next(); }; - useEffect(() => { setTimeout(play, 350); }, []); // eslint-disable-line react-hooks/exhaustive-deps - const renderLine = (item, i) => { - if (!item.t) return
; - return ( -
{item.t}
- ); + if (!item.t) return
; + return
{item.t}
; }; return ( @@ -101,34 +58,22 @@ export const TradeExecutionDemo = () => {
{">"}_
- Trade Execution + Token Search + Send
- + onMouseLeave={e => { e.currentTarget.style.color = "#3f3f46"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "transparent"; }}>{"↺"}
- -
-
- Agent -
-
- {leftLines.map(renderLine)} +
+
Terminal
+
+ {lines.map(renderLine)} {running &&
{"▋"}
}
-
- {done && ( - - )} + {!running && !done && } + {done && }
); diff --git a/docs/snippets/TradingQuickstartDemo.jsx b/docs/snippets/TradingQuickstartDemo.jsx index 2fe9f3744..3e8cd48e1 100644 --- a/docs/snippets/TradingQuickstartDemo.jsx +++ b/docs/snippets/TradingQuickstartDemo.jsx @@ -2,90 +2,57 @@ import { useState, useEffect, useRef } from "react"; export const TradingQuickstartDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", - }; + const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8", warn: "#fb923c" }; const steps = [ - { delay: 350, left: [{ t: "> install bankr skill from github.com/BankrBot/skills", c: "active" }], right: [ - { t: "── Bankr Wallet ────────────────────────", c: "dim" }, - { t: "GET /releases/latest", c: "muted" }, - ]}, - { delay: 700, left: [{ t: " ✓ Bankr skill installed", c: "success" }], right: [ - { t: " tag: bankr-wallet-v2.1.0", c: "success" }, - { t: " chains: base, eth, solana", c: "muted" }, - { t: " gas: sponsored", c: "muted" }, + { delay: 400, lines: [{ t: "> Swap 100 USDC for ETH on Base", c: "active" }] }, + { delay: 500, lines: [ + { t: " ── swap() ─────────────────────────────", c: "dim" }, + { t: " fromAsset: USDC toAsset: ETH amount: 100", c: "muted" }, ]}, - { delay: 500, left: [{ t: " ✓ Bankr wallet connected wlt_bankr_...", c: "success" }], right: [] }, - { delay: 500, left: [{ t: "> Buy $50 of ETH on Base", c: "active" }], right: [ - { t: "", c: "dim" }, - { t: "── Swap Quote ──────────────────────────", c: "dim" }, - { t: "POST /v1/swap/quote", c: "code" }, - { t: "Host: api.bankr.bot", c: "muted" }, + { delay: 700, lines: [ + { t: " ← quote ready", c: "muted" }, + { t: " 0.03512 ETH · price impact 0.09%", c: "code" }, ]}, - { delay: 700, left: [{ t: " fetching quote...", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: '{"fromAmount":"50.00 USDC",', c: "code" }, - { t: ' "toAmount":"0.01756 ETH",', c: "code" }, - { t: ' "priceImpact":"0.12%"}', c: "code" }, + { delay: 500, lines: [{ t: "", c: "dim" }, { t: " ── approval required ──────────────────────", c: "warn" }] }, + { delay: 400, lines: [ + { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, + { t: ' requestId: "req_swap01"', c: "muted" }, ]}, - { delay: 500, left: [{ t: " ← 0.01756 ETH · price impact 0.12%", c: "muted" }], right: [] }, - { delay: 500, left: [{ t: " impact below 1% — executing...", c: "muted" }], right: [] }, - { delay: 750, left: [{ t: " ✓ tx 0xb4f2...91ca confirmed", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── Transaction ─────────────────────────", c: "dim" }, - { t: " hash: 0xb4f2...91ca", c: "success" }, - { t: " status: confirmed", c: "success" }, - { t: " block: 28,419,042", c: "muted" }, + { delay: 500, lines: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }] }, + { delay: 1000, lines: [{ t: " ← user approved ✓", c: "success" }] }, + { delay: 500, lines: [ + { t: " ── get_request_status ─────────────────────", c: "dim" }, + { t: ' status: "confirmed" received: "0.03512 ETH"', c: "success" }, ]}, - { delay: 400, left: [{ t: " ✓ received 0.01756 ETH", c: "success", bold: true }], right: [] }, + { delay: 400, lines: [{ t: "", c: "dim" }, { t: " ✓ 0.03512 ETH received", c: "success" }] }, ]; - const [leftLines, setLeftLines] = useState([]); - const [rightLines, setRightLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const leftRef = useRef(null); - const rightRef = useRef(null); - - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); + const [lines, setLines] = useState([]); + const [running, setRunning] = useState(false); + const [done, setDone] = useState(false); + const [blink, setBlink] = useState(true); + const ref = useRef(null); - useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); + useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); + useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]); - const play = () => { - setLeftLines([]); - setRightLines([]); + const reset = () => { setLines([]); setRunning(false); setDone(false); }; + const run = () => { + if (running || done) return; setRunning(true); - setDone(false); let i = 0; const next = () => { if (i >= steps.length) { setRunning(false); setDone(true); return; } const s = steps[i]; - setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); - }, s.delay); + setTimeout(() => { setLines(p => [...p, ...s.lines]); i++; next(); }, s.delay); }; next(); }; - useEffect(() => { setTimeout(play, 350); }, []); // eslint-disable-line react-hooks/exhaustive-deps - const renderLine = (item, i) => { - if (!item.t) return
; - return ( -
{item.t}
- ); + if (!item.t) return
; + return
{item.t}
; }; return ( @@ -94,34 +61,26 @@ export const TradingQuickstartDemo = () => {
{">"}_
- Trading Quickstart + Swap Tokens
- + onMouseLeave={e => { e.currentTarget.style.color = "#3f3f46"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "transparent"; }}>{"↺"}
- -
+
- Agent + Terminal
-
- {leftLines.map(renderLine)} +
+ {lines.map(renderLine)} {running &&
{"▋"}
}
-
- {done && ( - - )} + {!running && !done && } + {done && }
); diff --git a/docs/snippets/WalletSetupDemo.jsx b/docs/snippets/WalletSetupDemo.jsx index 752e5098b..0da314852 100644 --- a/docs/snippets/WalletSetupDemo.jsx +++ b/docs/snippets/WalletSetupDemo.jsx @@ -2,195 +2,143 @@ import { useState, useEffect, useRef } from "react"; export const WalletSetupDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", - }; + const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8", warn: "#fb923c" }; + // Single-pane: all content flows in one stream. Config lines are indented/styled differently. const flows = { - cdp: [ - { delay: 400, left: [{ t: "> npx skills add coinbase/agentic-wallet-skills", c: "active" }], right: [ - { t: "── wallet.config.json ──────────────────", c: "dim" }, - { t: "{", c: "code" }, - ]}, - { delay: 600, left: [{ t: " ✓ skill installed", c: "success" }], right: [ - { t: ' "provider": "coinbase",', c: "code" }, - { t: ' "network": "base",', c: "code" }, - { t: ' "skills": ["agentic-wallet"]', c: "code" }, - { t: "}", c: "code" }, + desktop: [ + { delay: 450, lines: [{ t: "── claude_desktop_config.json ──────────", c: "dim" }] }, + { delay: 300, lines: [ + { t: '{ "mcpServers": {', c: "code" }, + { t: ' "base-account": {', c: "code" }, + { t: ' "url": "https://mcp.base.org"', c: "code" }, + { t: ' } } }', c: "code" }, ]}, - { delay: 500, left: [{ t: "> Sign in to my wallet with you@email.com", c: "active" }], right: [] }, - { delay: 700, left: [{ t: " ← OTP sent · checking...", c: "muted" }], right: [] }, - { delay: 650, left: [{ t: " ✓ CDP wallet connected 0x4a3f...b7c1", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: " address: 0x4a3f...b7c1", c: "success" }, - { t: " network: base-mainnet", c: "success" }, - { t: " status: ready", c: "success" }, + { delay: 600, lines: [{ t: " Restart Claude Desktop →", c: "muted" }] }, + { delay: 700, lines: [{ t: " ✓ base-account MCP connected", c: "success" }] }, + { delay: 500, lines: [{ t: "", c: "dim" }, { t: "> What's my USDC balance?", c: "active" }] }, + { delay: 650, lines: [{ t: " ← get_portfolio(chain=base)", c: "muted" }] }, + { delay: 500, lines: [ + { t: " USDC 245.80 $245.80", c: "success" }, + { t: " ETH 0.0412 $148.33", c: "success" }, + { t: " Total: $394.13 on Base ✓", c: "success" }, ]}, ], - sponge: [ - { delay: 400, left: [{ t: "> curl -X POST https://api.wallet.paysponge.com/...", c: "active" }], right: [ - { t: "── POST /api/agents/register ───────────", c: "dim" }, - { t: "Host: api.wallet.paysponge.com", c: "muted" }, - { t: "Content-Type: application/json", c: "muted" }, + chatgpt: [ + { delay: 450, lines: [{ t: " Settings → Connectors → Add custom connector", c: "muted" }] }, + { delay: 500, lines: [{ t: " Enter URL: https://mcp.base.org", c: "active" }] }, + { delay: 600, lines: [{ t: " ✓ base-account connector saved", c: "success" }] }, + { delay: 500, lines: [{ t: "", c: "dim" }, { t: "> Send 5 USDC to alice.base.eth", c: "active" }] }, + { delay: 600, lines: [{ t: " ← Authorization via keys.coinbase.com", c: "warn" }] }, + { delay: 500, lines: [ + { t: " Open to connect your Base Account:", c: "warn" }, + { t: " keys.coinbase.com/authorize", c: "warn" }, ]}, - { delay: 750, left: [{ t: ' ← {"apiKey": "sponge_live_..."}', c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "── 200 OK ──────────────────────────────", c: "dim" }, - { t: "{", c: "code" }, - { t: ' "apiKey": "sponge_live_abc...xyz",', c: "code" }, - { t: ' "walletId": "wlt_a1b2c3d4"', c: "code" }, - { t: "}", c: "code" }, - ]}, - { delay: 450, left: [{ t: "> export SPONGE_API_KEY=sponge_live_...", c: "active" }], right: [] }, - { delay: 400, left: [{ t: " ✓ Sponge wallet ready", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: " chains: base, ethereum, solana", c: "success" }, - { t: " x402: enabled", c: "success" }, + { delay: 900, lines: [{ t: " ✓ Base Account connected 0x4a3f...b7c1", c: "success" }] }, + { delay: 600, lines: [{ t: " ← approval required for this send", c: "warn" }] }, + { delay: 500, lines: [ + { t: " Open to approve: keys.coinbase.com/…", c: "warn" }, ]}, + { delay: 900, lines: [{ t: " ✓ 5 USDC sent to alice.base.eth", c: "success" }] }, ], - bankr: [ - { delay: 400, left: [{ t: "> install bankr skill from github.com/BankrBot/skills", c: "active" }], right: [ - { t: "── github.com/BankrBot/skills ──────────", c: "dim" }, - { t: "GET /releases/latest", c: "muted" }, + claude: [ + { delay: 450, lines: [{ t: "> claude mcp add --transport http base-account https://mcp.base.org", c: "active" }] }, + { delay: 600, lines: [ + { t: " ✓ MCP server added: base-account", c: "success" }, + { t: " ── .claude/settings.json updated", c: "dim" }, + ]}, + { delay: 500, lines: [{ t: "", c: "dim" }, { t: "> Show me my wallets", c: "active" }] }, + { delay: 600, lines: [{ t: " ← Connecting to mcp.base.org…", c: "muted" }] }, + { delay: 500, lines: [ + { t: " Authorize at: keys.coinbase.com/authorize", c: "warn" }, ]}, - { delay: 700, left: [{ t: " ✓ Bankr skill installed", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: " tag: bankr-wallet-v2.1.0", c: "success" }, - { t: " size: 142 KB", c: "muted" }, + { delay: 900, lines: [{ t: " ✓ Base Account: 0x4a3f...b7c1 ready", c: "success" }] }, + { delay: 500, lines: [ + { t: ' { type: "base-account", inSession: true }', c: "code" }, + { t: ' { type: "agent-wallet", inSession: false }', c: "code" }, ]}, - { delay: 500, left: [{ t: " ✓ Bankr wallet connected wlt_bankr_...", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: " chains: base, eth, solana, polygon", c: "success" }, - { t: " gas: sponsored", c: "success" }, - { t: " swaps: built-in", c: "success" }, + ], + codex: [ + { delay: 450, lines: [{ t: "> codex mcp add base-account --url https://mcp.base.org/", c: "active" }] }, + { delay: 600, lines: [ + { t: " ✓ MCP server added: base-account", c: "success" }, + { t: " ── codex.toml updated", c: "dim" }, ]}, + { delay: 500, lines: [{ t: "[mcp_servers.base-account]", c: "code" }, { t: 'url = "https://mcp.base.org/"', c: "code" }] }, + { delay: 600, lines: [{ t: "", c: "dim" }, { t: "> Show me my wallets", c: "active" }] }, + { delay: 700, lines: [{ t: " ✓ Base Account: 0x4a3f...b7c1 inSession=true", c: "success" }] }, ], }; - const [choice, setChoice] = useState(null); - const [leftLines, setLeftLines] = useState([]); - const [rightLines, setRightLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const leftRef = useRef(null); - const rightRef = useRef(null); - - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); + const [choice, setChoice] = useState(null); + const [lines, setLines] = useState([{ t: "> Choose your platform:", c: "muted" }]); + const [running, setRunning] = useState(false); + const [done, setDone] = useState(false); + const [blink, setBlink] = useState(true); + const ref = useRef(null); - useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); - - const reset = () => { - setChoice(null); - setLeftLines([{ t: "> Choose a wallet provider:", c: "muted" }]); - setRightLines([]); - setRunning(false); - setDone(false); - }; + useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); + useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]); - useEffect(() => { reset(); }, []); // eslint-disable-line react-hooks/exhaustive-deps + const reset = () => { setChoice(null); setLines([{ t: "> Choose your platform:", c: "muted" }]); setRunning(false); setDone(false); }; - const animateFlow = (key) => { + const pick = (key) => { + if (choice) return; + const labels = { desktop: "Claude Desktop", chatgpt: "ChatGPT", claude: "Claude Code", codex: "Codex" }; + setChoice(key); + setLines(prev => [...prev, { t: " [" + labels[key] + "]", c: "active" }]); const steps = flows[key]; - if (!steps) return; setRunning(true); - setDone(false); let i = 0; const next = () => { if (i >= steps.length) { setRunning(false); setDone(true); return; } const s = steps[i]; - setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); - }, s.delay); + setTimeout(() => { setLines(prev => [...prev, ...s.lines]); i++; next(); }, s.delay); }; - next(); - }; - - const pick = (w) => { - if (choice) return; - setChoice(w); - const label = w === "cdp" ? "CDP" : w === "sponge" ? "Sponge" : "Bankr"; - setLeftLines(prev => [...prev, { t: " [" + label + "]", c: "active" }]); - setTimeout(() => animateFlow(w), 150); + setTimeout(next, 200); }; const renderLine = (item, i) => { - if (!item.t) return
; - return ( -
{item.t}
- ); + if (!item.t) return
; + return
{item.t}
; }; - const btnBase = { - fontFamily: mono, fontSize: 12, - color: "#60a5fa", background: "transparent", - border: "1px solid #27272a", borderRadius: 4, - cursor: "pointer", padding: "1px 8px", - marginRight: 6, lineHeight: "20px", - }; + const btnBase = { fontFamily: mono, fontSize: 12, color: "#60a5fa", background: "transparent", border: "1px solid #27272a", borderRadius: 4, cursor: "pointer", padding: "2px 10px", marginRight: 6, lineHeight: "20px" }; const onEnter = (e) => { e.currentTarget.style.color = "#e4e4e7"; e.currentTarget.style.background = "#1c1c1e"; e.currentTarget.style.borderColor = "#3f3f46"; }; const onLeave = (e) => { e.currentTarget.style.color = "#60a5fa"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "#27272a"; }; return (
- {/* Chrome bar */}
{">"}_
- Wallet Setup + Connect mcp.base.org
+ onMouseLeave={e => { e.currentTarget.style.color = "#3f3f46"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "transparent"; }}>{"↺"}
- - {/* Terminal pane */} -
+
- Agent + Terminal
-
- {leftLines.map(renderLine)} - {!choice && leftLines.length > 0 && ( -
- pick: - - - +
+ {lines.map(renderLine)} + {!choice && ( +
+ {[["desktop", "Claude Desktop"], ["chatgpt", "ChatGPT"], ["claude", "Claude Code"], ["codex", "Codex"]].map(([k, l]) => ( + + ))}
)} {running &&
{"▋"}
}
- - {/* Footer */}
- {done && ( - - )} + {done && }
); diff --git a/docs/snippets/x402PayDemo.jsx b/docs/snippets/x402PayDemo.jsx index 7e5da9440..b7f7384e4 100644 --- a/docs/snippets/x402PayDemo.jsx +++ b/docs/snippets/x402PayDemo.jsx @@ -2,88 +2,56 @@ import { useState, useEffect, useRef } from "react"; export const X402PayDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", - }; + const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8", warn: "#fb923c" }; const steps = [ - { delay: 350, left: [{ t: "> GET api.coingecko.com/api/v3/simple/price", c: "active" }], right: [ - { t: "── Request 1 ───────────────────────────", c: "dim" }, - { t: "GET /api/v3/simple/price?ids=ethereum", c: "code" }, - { t: "Host: api.coingecko.com", c: "muted" }, + { delay: 400, lines: [{ t: "> Send 5 USDC to bob.base.eth", c: "active" }] }, + { delay: 500, lines: [ + { t: " ── send() ─────────────────────────────────", c: "dim" }, + { t: " recipient: bob.base.eth amount: 5 asset: USDC", c: "muted" }, ]}, - { delay: 650, left: [{ t: " ← 402 Payment Required", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "── Response 1 ──────────────────────────", c: "dim" }, - { t: "HTTP/1.1 402 Payment Required", c: "muted" }, - { t: "X-Payment-Required: {", c: "muted" }, - { t: ' "amount": "0.001",', c: "code" }, - { t: ' "asset": "USDC",', c: "code" }, - { t: ' "network": "base"', c: "code" }, - { t: "}", c: "muted" }, + { delay: 650, lines: [ + { t: " ── approval required ──────────────────────", c: "warn" }, + { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, + { t: ' requestId: "req_abc123"', c: "muted" }, ]}, - { delay: 500, left: [{ t: " paying 0.001 USDC via wallet...", c: "muted" }], right: [] }, - { delay: 700, left: [{ t: " ✓ tx confirmed 0x1a9f...c4e2", c: "success" }], right: [] }, - { delay: 450, left: [{ t: " → retrying with payment signature", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "── Request 2 ───────────────────────────", c: "dim" }, - { t: "GET /api/v3/simple/price?ids=ethereum", c: "code" }, - { t: "X-Payment-Sig: 0x1a9f...c4e2", c: "success" }, + { delay: 500, lines: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }] }, + { delay: 1100, lines: [{ t: " ← user opened and approved ✓", c: "success" }] }, + { delay: 500, lines: [ + { t: " ── get_request_status ─────────────────────", c: "dim" }, + { t: ' requestId: "req_abc123"', c: "muted" }, ]}, - { delay: 600, left: [{ t: " ← 200 OK", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── Response 2 ──────────────────────────", c: "dim" }, - { t: "HTTP/1.1 200 OK", c: "success" }, - { t: '{"ethereum":{"usd":2847.32}}', c: "code" }, + { delay: 500, lines: [ + { t: ' status: "confirmed"', c: "success" }, + { t: ' txHash: "0xf7e3...9a12"', c: "success" }, ]}, - { delay: 300, left: [{ t: " ETH $2,847.32 ↑ 2.3%", c: "code", bold: true }], right: [] }, + { delay: 300, lines: [{ t: "", c: "dim" }, { t: " ✓ 5 USDC sent to bob.base.eth", c: "success" }] }, ]; - const [leftLines, setLeftLines] = useState([]); - const [rightLines, setRightLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const leftRef = useRef(null); - const rightRef = useRef(null); - - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); + const [lines, setLines] = useState([]); + const [running, setRunning] = useState(false); + const [done, setDone] = useState(false); + const [blink, setBlink] = useState(true); + const ref = useRef(null); - useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); + useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); + useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]); - const play = () => { - setLeftLines([]); - setRightLines([]); + const reset = () => { setLines([]); setRunning(false); setDone(false); }; + const run = () => { + if (running || done) return; setRunning(true); - setDone(false); let i = 0; const next = () => { if (i >= steps.length) { setRunning(false); setDone(true); return; } - const s = steps[i]; - setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); - }, s.delay); + setTimeout(() => { setLines(p => [...p, ...steps[i].lines]); i++; next(); }, steps[i].delay); }; next(); }; - useEffect(() => { setTimeout(play, 350); }, []); // eslint-disable-line react-hooks/exhaustive-deps - const renderLine = (item, i) => { - if (!item.t) return
; - return ( -
{item.t}
- ); + if (!item.t) return
; + return
{item.t}
; }; return ( @@ -92,34 +60,22 @@ export const X402PayDemo = () => {
{">"}_
- x402 Pay Flow + Approval Mode
- + onMouseLeave={e => { e.currentTarget.style.color = "#3f3f46"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "transparent"; }}>{"↺"}
- -
-
- Agent -
-
- {leftLines.map(renderLine)} +
+
Terminal
+
+ {lines.map(renderLine)} {running &&
{"▋"}
}
-
- {done && ( - - )} + {!running && !done && } + {done && }
); From ee4952ef16b58e918e905a632261158768518e33 Mon Sep 17 00:00:00 2001 From: Youssef Date: Fri, 15 May 2026 01:02:37 +0100 Subject: [PATCH 02/36] update demo --- docs/ai-agents/quickstart.mdx | 103 +++++-- docs/ai-agents/setup/index.mdx | 92 +++++- docs/snippets/WalletSetupDemo.jsx | 448 +++++++++++++++++++++--------- 3 files changed, 482 insertions(+), 161 deletions(-) diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index 29e1abbfa..df672fd0c 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -1,7 +1,7 @@ --- title: "Quickstart" description: "Connect the Base Account MCP to your AI assistant in under 2 minutes" -keywords: ["Base Account MCP quickstart", "mcp.base.org setup", "Claude Desktop MCP", "ChatGPT MCP", "Claude Code MCP wallet"] +keywords: ["Base Account MCP quickstart", "mcp.base.org setup", "Claude Desktop MCP", "ChatGPT MCP", "Claude Code MCP wallet", "Cursor MCP", "VS Code MCP", "Windsurf MCP"] --- import { WalletSetupDemo } from "/snippets/WalletSetupDemo.jsx" @@ -15,11 +15,24 @@ Connect `mcp.base.org` to your AI assistant, then send your first prompt. ## Step 1 — Connect - - Open your Claude Desktop config file and add the Base Account MCP server: + + + Add to Claude + + + Paste `https://mcp.base.org` as the server URL and save. Works in Claude.ai (web, iOS, Android) and Claude Desktop. + + + Remote MCP integrations require a Claude Pro, Max, Team, or Enterprise plan. + + + **Claude Desktop config file** — if you prefer to configure manually, open **Settings → Developer → Edit Config** and add: - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json` - **Windows:** `%APPDATA%\Claude\claude_desktop_config.json` + | Platform | Config path | + |----------|-------------| + | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` | + | Windows | `%APPDATA%\Claude\claude_desktop_config.json` | + | Linux | `~/.config/Claude/claude_desktop_config.json` | ```json claude_desktop_config.json { @@ -31,34 +44,49 @@ Connect `mcp.base.org` to your AI assistant, then send your first prompt. } ``` - Restart Claude Desktop. A wallet icon will appear when the MCP is connected. + Save and restart Claude Desktop. A wallet icon will appear in the toolbar when connected. - 1. Open the ChatGPT app - 2. Go to **Settings → Connectors** - 3. Click **Add custom connector** - 4. Enter the server URL: + + Add to ChatGPT + - ``` + Then: + + 1. Enable **Developer Mode** if prompted (under Advanced) + 2. Click **Add custom connector** + 3. Enter the server URL: + + ```text https://mcp.base.org ``` - 5. Save and return to a conversation. ChatGPT will prompt you to authorize when you first use a wallet tool. + 4. Save. ChatGPT will prompt you to authorize when you first use a wallet tool. + + + MCP connectors require a ChatGPT Plus or Pro plan. + - Run this command in your terminal: + Run this in your terminal to add the server to the current project: ```bash Terminal claude mcp add --transport http base-account https://mcp.base.org ``` - Then start a Claude Code session. The `base-account` MCP will be available immediately. + To install globally (available across all your projects): + + ```bash Terminal + claude mcp add --transport http --scope user base-account https://mcp.base.org + ``` - To verify it's connected: + Verify it connected: ```bash Terminal claude mcp list ``` + + The `base-account` server will show with a tool count once active. You can also run `/mcp` inside a Claude Code session to see server status. ```bash Terminal @@ -73,15 +101,13 @@ Connect `mcp.base.org` to your AI assistant, then send your first prompt. ``` - Click to install automatically: - - Add to Cursor + Add to Cursor - Or add manually to `~/.cursor/mcp.json`: + Or add manually to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project): - ```json ~/.cursor/mcp.json + ```json mcp.json { "mcpServers": { "base-account": { @@ -90,15 +116,17 @@ Connect `mcp.base.org` to your AI assistant, then send your first prompt. } } ``` + + Restart Cursor, then open **Settings → MCP** to confirm `base-account` shows as active. - Install in VS Code + Add to VS Code - Or add to your VS Code MCP config: + Or add manually to `.vscode/mcp.json` (workspace) or your user MCP settings: - ```json settings.json + ```json .vscode/mcp.json { "servers": { "base-account": { @@ -108,9 +136,34 @@ Connect `mcp.base.org` to your AI assistant, then send your first prompt. } } ``` + + Open **Copilot Chat** in agent mode and confirm the wallet tools appear in the tool picker. + + + Add to `~/.codeium/windsurf/mcp_config.json`: + + ```json mcp_config.json + { + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + } + } + } + ``` + + Restart Windsurf. Open **Cascade** — the MCP tools will be available once connected. + + + You can also add MCP servers from the UI: open **Cascade** → click the **hammer icon** → **Add MCP Server**. + + + **Other clients** — Any MCP client that supports remote HTTP (Streamable HTTP) servers works with `https://mcp.base.org`. See the [setup guide](/ai-agents/setup) for Zed, JetBrains, Le Chat (Mistral), Warp, and others. On mobile, the Claude connector above works in the iOS and Android apps. + + ## Step 2 — Authorize The first time you use a wallet tool, your assistant will redirect you to `keys.coinbase.com` to connect your Base Account. You'll need a Coinbase account. Once authorized, all transactions still require individual approval at that same URL. @@ -142,7 +195,7 @@ Morpho lets your assistant query vaults, check APYs, and execute lending operati Add both MCPs to your config: - + ```json claude_desktop_config.json { "mcpServers": { @@ -162,7 +215,7 @@ Add both MCPs to your config: claude mcp add morpho --transport http https://mcp.morpho.org/ ``` - + Add a second entry alongside `base-account`: ```json diff --git a/docs/ai-agents/setup/index.mdx b/docs/ai-agents/setup/index.mdx index 255d22206..7110518de 100644 --- a/docs/ai-agents/setup/index.mdx +++ b/docs/ai-agents/setup/index.mdx @@ -1,7 +1,7 @@ --- title: "Setup" -description: "Connect the Base Account MCP to Claude Desktop, ChatGPT, Claude Code, Codex, Cursor, VS Code, and more" -keywords: ["mcp.base.org setup", "Base Account MCP install", "Claude Desktop MCP config", "ChatGPT MCP connector", "Claude Code MCP"] +description: "Connect the Base Account MCP to Claude Desktop, Claude.ai, ChatGPT, Claude Code, Cursor, VS Code, Windsurf, Zed, JetBrains, Le Chat, Warp, and more" +keywords: ["mcp.base.org setup", "Base Account MCP install", "Claude Desktop MCP config", "ChatGPT MCP connector", "Claude Code MCP", "Cursor MCP", "VS Code MCP", "Windsurf MCP", "Zed MCP", "JetBrains MCP"] --- import { X402PayDemo } from "/snippets/x402PayDemo.jsx" @@ -20,12 +20,19 @@ Every individual transaction requires approval at `keys.coinbase.com`. Your assi ### Claude Desktop -Open your config file and add the `base-account` server: + + Add to Claude + + +Click the button above to open the connector settings directly, paste `https://mcp.base.org`, and save. + +**Or edit the config file manually:** | Platform | Config path | |----------|-------------| | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` | | Windows | `%APPDATA%\Claude\claude_desktop_config.json` | +| Linux | `~/.config/Claude/claude_desktop_config.json` | ```json claude_desktop_config.json { @@ -43,11 +50,14 @@ Restart Claude Desktop. The wallet MCP will show as connected in the toolbar. ### ChatGPT -1. Open the **ChatGPT** app -2. Go to **Settings → Connectors** -3. Click **Add custom connector** -4. Enter `https://mcp.base.org` as the server URL -5. Save + + Add to ChatGPT + + +1. Enable **Developer Mode** if prompted (under Advanced) +2. Click **Add custom connector** +3. Enter `https://mcp.base.org` as the server URL +4. Save On first use, ChatGPT will prompt you to authorize your Coinbase account. @@ -91,7 +101,7 @@ url = "https://mcp.base.org/" ### Cursor - One-click install in Cursor + Add to Cursor Or add manually to `~/.cursor/mcp.json`: @@ -111,7 +121,7 @@ Or add manually to `~/.cursor/mcp.json`: ### VS Code - Install in VS Code + Add to VS Code Or add to your VS Code MCP settings: @@ -143,6 +153,68 @@ Add to `~/.codeium/windsurf/mcp_config.json`: } ``` +You can also add servers from the UI: open **Cascade** → click the **hammer icon** → **Add MCP Server**. + +--- + +### Zed + +Add to your Zed `settings.json` (`~/.config/zed/settings.json` on macOS/Linux, `%APPDATA%\Zed\settings.json` on Windows): + +```json settings.json +{ + "context_servers": { + "base-account": { + "source": "custom", + "command": { + "path": "npx", + "args": ["-y", "mcp-remote", "https://mcp.base.org"] + } + } + } +} +``` + + + Zed does not yet support native remote HTTP MCP servers. The snippet above uses [`mcp-remote`](https://github.com/geelen/mcp-remote) as a local proxy bridge — no pre-install needed. See [Zed MCP docs](https://zed.dev/docs/ai/mcp) for the latest config format. + + +--- + +### JetBrains AI Assistant + +1. Open your JetBrains IDE (IntelliJ, WebStorm, PyCharm, etc.) +2. Go to **Settings** → **AI Assistant** → **Model Context Protocol (MCP)** +3. Click **Add** and select **HTTP** as the transport +4. Enter `https://mcp.base.org` as the server URL +5. Apply and restart the IDE + +See [JetBrains AI Assistant MCP docs](https://www.jetbrains.com/help/ai-assistant/mcp.html) for full configuration options. + +--- + +### Le Chat (Mistral) + +1. Open [mistral.ai](https://mistral.ai) and sign in +2. Go to **Settings** → **Connectors** +3. Click **Add custom connector** +4. Enter `https://mcp.base.org` as the server URL +5. Save and return to a chat + +See [Le Chat MCP connector docs](https://help.mistral.ai/en/articles/393572-configuring-a-custom-connector) for full details. + +--- + +### Warp + +1. Open [Warp](https://www.warp.dev/) terminal +2. Go to **Settings** → **AI** → **MCP Servers** +3. Click **Add server** +4. Select **SSE** as the transport and enter `https://mcp.base.org` as the URL +5. Save — the server starts automatically with Warp + +See [Warp MCP docs](https://docs.warp.dev/knowledge-and-collaboration/mcp) for CLI-based setup. + --- ## Approval mode diff --git a/docs/snippets/WalletSetupDemo.jsx b/docs/snippets/WalletSetupDemo.jsx index 0da314852..f45f867b0 100644 --- a/docs/snippets/WalletSetupDemo.jsx +++ b/docs/snippets/WalletSetupDemo.jsx @@ -1,144 +1,340 @@ import { useState, useEffect, useRef } from "react"; export const WalletSetupDemo = () => { - const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8", warn: "#fb923c" }; - - // Single-pane: all content flows in one stream. Config lines are indented/styled differently. - const flows = { - desktop: [ - { delay: 450, lines: [{ t: "── claude_desktop_config.json ──────────", c: "dim" }] }, - { delay: 300, lines: [ - { t: '{ "mcpServers": {', c: "code" }, - { t: ' "base-account": {', c: "code" }, - { t: ' "url": "https://mcp.base.org"', c: "code" }, - { t: ' } } }', c: "code" }, - ]}, - { delay: 600, lines: [{ t: " Restart Claude Desktop →", c: "muted" }] }, - { delay: 700, lines: [{ t: " ✓ base-account MCP connected", c: "success" }] }, - { delay: 500, lines: [{ t: "", c: "dim" }, { t: "> What's my USDC balance?", c: "active" }] }, - { delay: 650, lines: [{ t: " ← get_portfolio(chain=base)", c: "muted" }] }, - { delay: 500, lines: [ - { t: " USDC 245.80 $245.80", c: "success" }, - { t: " ETH 0.0412 $148.33", c: "success" }, - { t: " Total: $394.13 on Base ✓", c: "success" }, - ]}, - ], - chatgpt: [ - { delay: 450, lines: [{ t: " Settings → Connectors → Add custom connector", c: "muted" }] }, - { delay: 500, lines: [{ t: " Enter URL: https://mcp.base.org", c: "active" }] }, - { delay: 600, lines: [{ t: " ✓ base-account connector saved", c: "success" }] }, - { delay: 500, lines: [{ t: "", c: "dim" }, { t: "> Send 5 USDC to alice.base.eth", c: "active" }] }, - { delay: 600, lines: [{ t: " ← Authorization via keys.coinbase.com", c: "warn" }] }, - { delay: 500, lines: [ - { t: " Open to connect your Base Account:", c: "warn" }, - { t: " keys.coinbase.com/authorize", c: "warn" }, - ]}, - { delay: 900, lines: [{ t: " ✓ Base Account connected 0x4a3f...b7c1", c: "success" }] }, - { delay: 600, lines: [{ t: " ← approval required for this send", c: "warn" }] }, - { delay: 500, lines: [ - { t: " Open to approve: keys.coinbase.com/…", c: "warn" }, - ]}, - { delay: 900, lines: [{ t: " ✓ 5 USDC sent to alice.base.eth", c: "success" }] }, - ], - claude: [ - { delay: 450, lines: [{ t: "> claude mcp add --transport http base-account https://mcp.base.org", c: "active" }] }, - { delay: 600, lines: [ - { t: " ✓ MCP server added: base-account", c: "success" }, - { t: " ── .claude/settings.json updated", c: "dim" }, - ]}, - { delay: 500, lines: [{ t: "", c: "dim" }, { t: "> Show me my wallets", c: "active" }] }, - { delay: 600, lines: [{ t: " ← Connecting to mcp.base.org…", c: "muted" }] }, - { delay: 500, lines: [ - { t: " Authorize at: keys.coinbase.com/authorize", c: "warn" }, - ]}, - { delay: 900, lines: [{ t: " ✓ Base Account: 0x4a3f...b7c1 ready", c: "success" }] }, - { delay: 500, lines: [ - { t: ' { type: "base-account", inSession: true }', c: "code" }, - { t: ' { type: "agent-wallet", inSession: false }', c: "code" }, - ]}, - ], - codex: [ - { delay: 450, lines: [{ t: "> codex mcp add base-account --url https://mcp.base.org/", c: "active" }] }, - { delay: 600, lines: [ - { t: " ✓ MCP server added: base-account", c: "success" }, - { t: " ── codex.toml updated", c: "dim" }, - ]}, - { delay: 500, lines: [{ t: "[mcp_servers.base-account]", c: "code" }, { t: 'url = "https://mcp.base.org/"', c: "code" }] }, - { delay: 600, lines: [{ t: "", c: "dim" }, { t: "> Show me my wallets", c: "active" }] }, - { delay: 700, lines: [{ t: " ✓ Base Account: 0x4a3f...b7c1 inSession=true", c: "success" }] }, - ], - }; + const sans = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"; + const serif = "'Tiempos Headline','Iowan Old Style','Source Serif Pro',ui-serif,Georgia,serif"; + const mono = "ui-monospace,'SF Mono','Cascadia Code',Menlo,Monaco,Consolas,monospace"; - const [choice, setChoice] = useState(null); - const [lines, setLines] = useState([{ t: "> Choose your platform:", c: "muted" }]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const ref = useRef(null); - - useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); - useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]); - - const reset = () => { setChoice(null); setLines([{ t: "> Choose your platform:", c: "muted" }]); setRunning(false); setDone(false); }; - - const pick = (key) => { - if (choice) return; - const labels = { desktop: "Claude Desktop", chatgpt: "ChatGPT", claude: "Claude Code", codex: "Codex" }; - setChoice(key); - setLines(prev => [...prev, { t: " [" + labels[key] + "]", c: "active" }]); - const steps = flows[key]; - setRunning(true); - let i = 0; - const next = () => { - if (i >= steps.length) { setRunning(false); setDone(true); return; } - const s = steps[i]; - setTimeout(() => { setLines(prev => [...prev, ...s.lines]); i++; next(); }, s.delay); - }; - setTimeout(next, 200); + const c = { + bg: "#1f1e1d", + header: "#262624", + border: "#34322f", + inputBg: "#2a2926", + text: "#f5f4ed", + body: "#e8e4dc", + muted: "#a8a39d", + dim: "#6b6663", + accent: "#D97757", + bubble: "#2c2b28", + bubbleText: "#f5f4ed", + code: "#e89972", + codeBg: "rgba(217,119,87,0.12)", + toolBg: "#272622", + toolBorder: "#3a3835", + success: "#a3c585", }; - const renderLine = (item, i) => { - if (!item.t) return
; - return
{item.t}
; + const examples = [ + { + prompt: "What's my USDC balance on Base?", + tool: { server: "base-account", action: "get_portfolio", args: { chain: "base" } }, + reply: { + intro: "Here's your portfolio on Base:", + rows: [ + { token: "USDC", amount: "245.80", value: "$245.80" }, + { token: "ETH", amount: "0.0412", value: "$148.33" }, + ], + total: "$394.13", + }, + }, + { + prompt: "Send 1 USDC to coinbase.base.eth", + tool: { server: "base-account", action: "send", args: { to: "coinbase.base.eth", amount: "1 USDC" } }, + reply: { + intro: "I prepared the transaction. Approve it to send:", + approval: "keys.coinbase.com/approve/req_a4f7c2", + confirm: "Sent 1 USDC to coinbase.base.eth", + }, + }, + { + prompt: "Find the best USDC vault on Base by APY", + tool: { server: "morpho", action: "find_best_vault", args: { asset: "USDC", chain: "base" } }, + reply: { + intro: "Top USDC vaults on Base right now:", + rows: [ + { token: "Steakhouse USDC", amount: "8.42% APY", value: "$24.1M TVL" }, + { token: "Re7 USDC", amount: "7.91% APY", value: "$18.7M TVL" }, + ], + total: null, + }, + }, + ]; + + const [activeIdx, setActiveIdx] = useState(null); // which example is playing + const [step, setStep] = useState(0); // 0=just user msg, 1=thinking, 2=tool, 3=intro, 4=details, 5=done + const scrollRef = useRef(null); + const timersRef = useRef([]); + + const clearTimers = () => { timersRef.current.forEach(clearTimeout); timersRef.current = []; }; + + useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [step, activeIdx]); + useEffect(() => () => clearTimers(), []); + + const pick = (idx) => { + if (activeIdx !== null) return; + setActiveIdx(idx); + setStep(0); + clearTimers(); + const seq = [[350, 1], [600, 2], [800, 3], [600, 4], [500, 5]]; + let cumulative = 0; + seq.forEach(([d, s]) => { + cumulative += d; + timersRef.current.push(setTimeout(() => setStep(s), cumulative)); + }); }; - const btnBase = { fontFamily: mono, fontSize: 12, color: "#60a5fa", background: "transparent", border: "1px solid #27272a", borderRadius: 4, cursor: "pointer", padding: "2px 10px", marginRight: 6, lineHeight: "20px" }; - const onEnter = (e) => { e.currentTarget.style.color = "#e4e4e7"; e.currentTarget.style.background = "#1c1c1e"; e.currentTarget.style.borderColor = "#3f3f46"; }; - const onLeave = (e) => { e.currentTarget.style.color = "#60a5fa"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "#27272a"; }; + const reset = () => { clearTimers(); setActiveIdx(null); setStep(0); }; - return ( -
-
-
- {">"}_ + const ex = activeIdx !== null ? examples[activeIdx] : null; + + // ----- UI bits ----- + + const TrafficLights = () => ( +
+ + + +
+ ); + + const UserBubble = ({ children }) => ( +
+
{children}
+
+ ); + + const ToolCall = ({ tool }) => ( +
+
+ + + + + + + + {tool.server} + · + {tool.action} + ( + {Object.entries(tool.args).map(([k, v], i, arr) => ( + + {k}: + "{v}" + {i < arr.length - 1 && , } + + ))} + ) + +
+
+ ); + + const Thinking = () => ( +
+ + {[0, 1, 2].map(i => ( + + ))} + + Thinking +
+ ); + + const ResponseText = ({ children }) => ( +
{children}
+ ); + + const ResponseRows = ({ rows }) => ( +
+ {rows.map((r, i) => ( +
+ + {r.token} + {r.amount} + {r.value}
- Connect mcp.base.org + ))} +
+ ); + + const ApprovalLink = ({ url }) => ( +
+ + + + + + {url} + +
+ ); + + const Confirm = ({ text }) => ( +
+ + + + {text} +
+ ); + + const Total = ({ value }) => ( +
+ Total + {value} +
+ ); + + const ChipBtn = ({ onClick, children }) => { + const [hover, setHover] = useState(false); + return ( + + ); + }; + + return ( +
+ {/* keyframes */} + + + {/* Header */} +
+ + + Base wallet + +
- + {activeIdx !== null && ( + + )}
-
-
- Terminal -
-
- {lines.map(renderLine)} - {!choice && ( -
- {[["desktop", "Claude Desktop"], ["chatgpt", "ChatGPT"], ["claude", "Claude Code"], ["codex", "Codex"]].map(([k, l]) => ( - + + {/* Chat area */} +
+ {!ex && ( +
+
+ Try asking your assistant once mcp.base.org is connected: +
+
+ {examples.map((e, i) => ( + pick(i)}>{e.prompt} ))}
- )} - {running &&
{"▋"}
} -
+
+ )} + + {ex && ( + <> + {ex.prompt} + + {step >= 1 && step < 3 && } + {step >= 2 && } + + {step >= 3 && {ex.reply.intro}} + + {step >= 4 && ex.reply.rows && } + {step >= 4 && ex.reply.total && } + {step >= 4 && ex.reply.approval && } + {step >= 5 && ex.reply.confirm && } + + )}
-
- {done && } + + {/* Input area */} +
+
+ + + Write a message... + + + Sonnet 4.6 + + + + + + +
+
+ Demo · Your assistant approves every transaction at keys.coinbase.com +
); From 540a7f5e49b26e4fa86b89bd2180b000f5592447 Mon Sep 17 00:00:00 2001 From: Youssef Date: Fri, 15 May 2026 01:21:31 +0100 Subject: [PATCH 03/36] update quickstart --- docs/ai-agents/quickstart.mdx | 4 +- docs/snippets/WalletSetupDemo.jsx | 269 ++++++++++++++++++------------ 2 files changed, 166 insertions(+), 107 deletions(-) diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index df672fd0c..7a86f4859 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -1,6 +1,6 @@ --- title: "Quickstart" -description: "Connect the Base Account MCP to your AI assistant in under 2 minutes" +description: "Connect the Base MCP to your AI assistant in under 2 minutes" keywords: ["Base Account MCP quickstart", "mcp.base.org setup", "Claude Desktop MCP", "ChatGPT MCP", "Claude Code MCP wallet", "Cursor MCP", "VS Code MCP", "Windsurf MCP"] --- @@ -181,7 +181,7 @@ What's my USDC balance on Base? ``` ```text -Send 1 USDC to coinbase.base.eth +Send 1 USDC to vitalik.base.eth ``` Every send, swap, or sign operation will give you an approval link. Open it, review the transaction, and confirm. diff --git a/docs/snippets/WalletSetupDemo.jsx b/docs/snippets/WalletSetupDemo.jsx index f45f867b0..946101314 100644 --- a/docs/snippets/WalletSetupDemo.jsx +++ b/docs/snippets/WalletSetupDemo.jsx @@ -24,66 +24,78 @@ export const WalletSetupDemo = () => { success: "#a3c585", }; + // Each example is a sequence of events. Each event reveals one block. + // Block types: thinking, tool, text, rows, approval, confirm + // (thinking auto-hides once the next event renders) const examples = [ { - prompt: "What's my USDC balance on Base?", - tool: { server: "base-account", action: "get_portfolio", args: { chain: "base" } }, - reply: { - intro: "Here's your portfolio on Base:", - rows: [ - { token: "USDC", amount: "245.80", value: "$245.80" }, - { token: "ETH", amount: "0.0412", value: "$148.33" }, - ], - total: "$394.13", - }, + prompt: "Send 5 USDC to vitalik.base.eth", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "base-account", action: "send", args: { to: "vitalik.base.eth", asset: "USDC", amount: "5" } } }, + { delay: 550, type: "text", text: "Resolved vitalik.base.eth → 0xd8dA…6045. Approve to send:" }, + { delay: 250, type: "approval", url: "keys.coinbase.com/approve/req_a4f7c2" }, + { delay: 1100, type: "confirm", text: "Sent 5 USDC to vitalik.base.eth" }, + ], }, { - prompt: "Send 1 USDC to coinbase.base.eth", - tool: { server: "base-account", action: "send", args: { to: "coinbase.base.eth", amount: "1 USDC" } }, - reply: { - intro: "I prepared the transaction. Approve it to send:", - approval: "keys.coinbase.com/approve/req_a4f7c2", - confirm: "Sent 1 USDC to coinbase.base.eth", - }, + prompt: "Swap 0.05 ETH to USDC on Base — best rate", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "aerodrome", action: "get_quote", args: { from: "0.05 ETH", to: "USDC" } } }, + { delay: 700, type: "tool", tool: { server: "uniswap-v3", action: "get_quote", args: { from: "0.05 ETH", to: "USDC" } } }, + { delay: 600, type: "text", text: "Routed across two Base DEXes — Uniswap v3 has the better fill:" }, + { delay: 250, type: "rows", rows: [ + { token: "Aerodrome", amount: "178.92 USDC", value: "0.30% fee · slippage 0.18%" }, + { token: "Uniswap v3 (best)", amount: "179.41 USDC", value: "0.05% fee · slippage 0.12%" }, + ]}, + { delay: 700, type: "tool", tool: { server: "uniswap-v3", action: "prepare_swap", args: { route: "ETH→USDC", min_out: "179.20 USDC" } } }, + { delay: 450, type: "approval", url: "keys.coinbase.com/approve/req_8c2e4d" }, + { delay: 1100, type: "confirm", text: "Swapped 0.05 ETH → 179.41 USDC on Uniswap v3" }, + ], }, { - prompt: "Find the best USDC vault on Base by APY", - tool: { server: "morpho", action: "find_best_vault", args: { asset: "USDC", chain: "base" } }, - reply: { - intro: "Top USDC vaults on Base right now:", - rows: [ - { token: "Steakhouse USDC", amount: "8.42% APY", value: "$24.1M TVL" }, - { token: "Re7 USDC", amount: "7.91% APY", value: "$18.7M TVL" }, - ], - total: null, - }, + prompt: "Find the best USDC yield on Base and deposit 100", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "morpho", action: "list_vaults", args: { asset: "USDC", chain: "base" } } }, + { delay: 700, type: "tool", tool: { server: "moonwell", action: "list_markets", args: { asset: "USDC", chain: "base" } } }, + { delay: 600, type: "text", text: "Compared Morpho vaults and Moonwell markets — top USDC yields on Base:" }, + { delay: 250, type: "rows", rows: [ + { token: "Morpho · Steakhouse USDC", amount: "8.42% APY", value: "$24.1M TVL · winner" }, + { token: "Morpho · Re7 USDC", amount: "7.91% APY", value: "$18.7M TVL" }, + { token: "Moonwell · USDC market", amount: "5.13% APY", value: "$41.2M supplied" }, + ]}, + { delay: 700, type: "tool", tool: { server: "morpho", action: "prepare_deposit", args: { vault: "Steakhouse USDC", amount: "100 USDC" } } }, + { delay: 450, type: "approval", url: "keys.coinbase.com/approve/req_b9f2a1" }, + { delay: 1100, type: "confirm", text: "Deposited 100 USDC into Steakhouse USDC · earning 8.42% APY" }, + ], }, ]; - const [activeIdx, setActiveIdx] = useState(null); // which example is playing - const [step, setStep] = useState(0); // 0=just user msg, 1=thinking, 2=tool, 3=intro, 4=details, 5=done + const [activeIdx, setActiveIdx] = useState(null); + const [eventIdx, setEventIdx] = useState(0); const scrollRef = useRef(null); const timersRef = useRef([]); const clearTimers = () => { timersRef.current.forEach(clearTimeout); timersRef.current = []; }; - useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [step, activeIdx]); + useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [eventIdx, activeIdx]); useEffect(() => () => clearTimers(), []); const pick = (idx) => { if (activeIdx !== null) return; setActiveIdx(idx); - setStep(0); + setEventIdx(0); clearTimers(); - const seq = [[350, 1], [600, 2], [800, 3], [600, 4], [500, 5]]; let cumulative = 0; - seq.forEach(([d, s]) => { - cumulative += d; - timersRef.current.push(setTimeout(() => setStep(s), cumulative)); + examples[idx].events.forEach((e, i) => { + cumulative += e.delay; + timersRef.current.push(setTimeout(() => setEventIdx(i + 1), cumulative)); }); }; - const reset = () => { clearTimers(); setActiveIdx(null); setStep(0); }; + const reset = () => { clearTimers(); setActiveIdx(null); setEventIdx(0); }; const ex = activeIdx !== null ? examples[activeIdx] : null; @@ -98,29 +110,34 @@ export const WalletSetupDemo = () => { ); const UserBubble = ({ children }) => ( -
-
+
{children}
); - const ToolCall = ({ tool }) => ( -
-
( +
+
- - - - - + + {completed ? ( + + ) : ( + + + + + )} - + {tool.server} · {tool.action} @@ -139,7 +156,7 @@ export const WalletSetupDemo = () => { ); const Thinking = () => ( -
+
{[0, 1, 2].map(i => ( {
); - const ResponseText = ({ children }) => ( -
{children}
+ const ResponseText = ({ children, top }) => ( +
{children}
); const ResponseRows = ({ rows }) => ( -
+
{rows.map((r, i) => ( -
- - {r.token} + + {r.token} {r.amount} {r.value}
@@ -176,18 +193,20 @@ export const WalletSetupDemo = () => { ); const ApprovalLink = ({ url }) => ( -
- + - + - {url} + {url}
); @@ -204,17 +223,6 @@ export const WalletSetupDemo = () => {
); - const Total = ({ value }) => ( -
- Total - {value} -
- ); - const ChipBtn = ({ onClick, children }) => { const [hover, setHover] = useState(false); return ( @@ -222,28 +230,87 @@ export const WalletSetupDemo = () => { onClick={onClick} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)} + className="wsd-chip" style={{ - fontFamily: sans, fontSize: 13, lineHeight: 1.35, + fontFamily: serif, lineHeight: 1.4, color: hover ? c.text : c.body, - background: hover ? c.toolBg : "transparent", + background: hover ? c.toolBg : c.header, border: `1px solid ${hover ? c.accent : c.toolBorder}`, - borderRadius: 12, padding: "10px 14px", + borderRadius: 14, textAlign: "left", cursor: "pointer", transition: "all 0.15s ease", + display: "flex", alignItems: "center", justifyContent: "space-between", + gap: 14, width: "100%", }}> - {children} + {children} + + + ); }; + // Render the events shown so far for the active example + const renderEvents = () => { + if (!ex) return null; + const shown = ex.events.slice(0, eventIdx); + return shown.map((event, i) => { + // Hide thinking once any later event has appeared + if (event.type === "thinking") { + if (i < shown.length - 1) return null; + return ; + } + if (event.type === "tool") { + // Mark as completed once any later non-thinking event has appeared + const hasLater = shown.slice(i + 1).some(e => e.type !== "thinking"); + return ; + } + if (event.type === "text") return {event.text}; + if (event.type === "rows") return ; + if (event.type === "approval") return ; + if (event.type === "confirm") return ; + return null; + }); + }; + return (
- {/* keyframes */} - + {/* keyframes + responsive */} + {/* Header */}
{
{/* Chat area */} -
+
{!ex && (
-
- Try asking your assistant once mcp.base.org is connected: +
+ Try asking your assistant once mcp.base.org is connected:
-
+
{examples.map((e, i) => ( pick(i)}>{e.prompt} ))} @@ -288,22 +355,13 @@ export const WalletSetupDemo = () => { {ex && ( <> {ex.prompt} - - {step >= 1 && step < 3 && } - {step >= 2 && } - - {step >= 3 && {ex.reply.intro}} - - {step >= 4 && ex.reply.rows && } - {step >= 4 && ex.reply.total && } - {step >= 4 && ex.reply.approval && } - {step >= 5 && ex.reply.confirm && } + {renderEvents()} )}
{/* Input area */} -
+
{ - Write a message... - + Sonnet 4.6 - +
-
Demo · Your assistant approves every transaction at keys.coinbase.com
From 1febefd208909b13ddc74139e05ed1b56461ec99 Mon Sep 17 00:00:00 2001 From: Youssef Date: Fri, 15 May 2026 01:28:18 +0100 Subject: [PATCH 04/36] remove sections --- docs/docs.json | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/docs/docs.json b/docs/docs.json index bddf6d58f..389349666 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -682,17 +682,9 @@ "group": "Quickstart", "pages": ["ai-agents/quickstart"] }, - { - "group": "Setup", - "pages": [ - "ai-agents/setup/index", - "ai-agents/setup/agent-builder-codes" - ] - }, { "group": "Guides", "pages": [ - "ai-agents/guides/index", "ai-agents/guides/check-balance", "ai-agents/guides/send-tokens", "ai-agents/guides/swap-tokens", @@ -705,28 +697,6 @@ { "group": "Plugins", "pages": ["ai-agents/plugins/morpho"] - }, - { - "group": "Payments", - "pages": ["ai-agents/payments"] - }, - { - "group": "Skills", - "pages": [ - "ai-agents/skills/index", - { - "group": "Wallets", - "pages": [ - "ai-agents/skills/wallets/cdp-agentic-wallet" - ] - }, - { - "group": "Payments", - "pages": [ - "ai-agents/skills/payments/cdp-payment-skills" - ] - } - ] } ] } From 3591d8f254e08c66ce212c601e2abb4a499049ff Mon Sep 17 00:00:00 2001 From: Youssef Date: Fri, 15 May 2026 01:33:33 +0100 Subject: [PATCH 05/36] update base mcp naming --- docs/ai-agents/guides/batch-calls.mdx | 4 ++-- docs/ai-agents/guides/check-balance.mdx | 2 +- docs/ai-agents/guides/index.mdx | 4 ++-- docs/ai-agents/guides/pay-for-services.mdx | 2 +- docs/ai-agents/guides/send-tokens.mdx | 4 ++-- docs/ai-agents/guides/sign-messages.mdx | 6 +++--- docs/ai-agents/guides/swap-tokens.mdx | 4 ++-- docs/ai-agents/guides/view-history.mdx | 2 +- docs/ai-agents/index.mdx | 14 +++++++------- docs/ai-agents/payments.mdx | 8 ++++---- docs/ai-agents/plugins/morpho.mdx | 8 ++++---- docs/ai-agents/quickstart.mdx | 4 ++-- docs/ai-agents/setup/index.mdx | 6 +++--- docs/ai-agents/skills/index.mdx | 6 +++--- .../skills/payments/cdp-payment-skills.mdx | 2 +- .../skills/wallets/cdp-agentic-wallet.mdx | 2 +- 16 files changed, 39 insertions(+), 39 deletions(-) diff --git a/docs/ai-agents/guides/batch-calls.mdx b/docs/ai-agents/guides/batch-calls.mdx index f74b05bff..389545c48 100644 --- a/docs/ai-agents/guides/batch-calls.mdx +++ b/docs/ai-agents/guides/batch-calls.mdx @@ -1,6 +1,6 @@ --- title: "Execute Contract Calls" -description: "Batch multiple contract interactions into a single user approval using send_calls and the Base Account MCP" +description: "Batch multiple contract interactions into a single user approval using send_calls and Base MCP" keywords: ["send_calls MCP", "batch contract calls AI", "EIP-5792 AI", "DeFi AI agent", "Morpho AI Base", "batch transaction AI"] --- @@ -37,7 +37,7 @@ Repay all my Morpho debt Protocol plugins like Morpho return a `calls` array and `chainId` from their `prepare_*` tools. The calls include any required token approvals and the protocol interaction itself. - Passes the `calls` array and hex `chainId` to the Base Account MCP. + Passes the `calls` array and hex `chainId` to Base MCP. Open the `keys.coinbase.com` link to review all calls in the batch before signing. diff --git a/docs/ai-agents/guides/check-balance.mdx b/docs/ai-agents/guides/check-balance.mdx index a80b8088b..8cc99b4ce 100644 --- a/docs/ai-agents/guides/check-balance.mdx +++ b/docs/ai-agents/guides/check-balance.mdx @@ -1,6 +1,6 @@ --- title: "Check Balance & Portfolio" -description: "View your token balances, portfolio value, and wallet details using the Base Account MCP" +description: "View your token balances, portfolio value, and wallet details using Base MCP" keywords: ["check balance AI", "get_portfolio MCP", "get_wallets MCP", "Base wallet balance AI assistant"] --- diff --git a/docs/ai-agents/guides/index.mdx b/docs/ai-agents/guides/index.mdx index 05528311c..bf938918b 100644 --- a/docs/ai-agents/guides/index.mdx +++ b/docs/ai-agents/guides/index.mdx @@ -1,7 +1,7 @@ --- title: "Guides" -description: "Step-by-step guides for common things to do with your Base Account MCP" -keywords: ["Base Account MCP guides", "send tokens AI", "swap tokens AI", "check balance AI", "x402 payments AI"] +description: "Step-by-step guides for common things to do with Base MCP" +keywords: ["Base MCP guides", "send tokens AI", "swap tokens AI", "check balance AI", "x402 payments AI"] --- diff --git a/docs/ai-agents/guides/pay-for-services.mdx b/docs/ai-agents/guides/pay-for-services.mdx index 6587f588c..b7902b551 100644 --- a/docs/ai-agents/guides/pay-for-services.mdx +++ b/docs/ai-agents/guides/pay-for-services.mdx @@ -49,7 +49,7 @@ Sign in to my wallet with your@email.com The `pay-for-service` skill handles the full flow: discovers the API, pays in USDC, retries with the payment signature, and returns the data. -x402 support for the Base Account MCP is coming soon. Once available, no separate wallet skill will be needed — your Base Account will pay directly. +x402 support for Base MCP is coming soon. Once available, no separate wallet skill will be needed — your Base Account will pay directly. ## How the x402 flow works diff --git a/docs/ai-agents/guides/send-tokens.mdx b/docs/ai-agents/guides/send-tokens.mdx index bddbe3f29..cc7e971aa 100644 --- a/docs/ai-agents/guides/send-tokens.mdx +++ b/docs/ai-agents/guides/send-tokens.mdx @@ -1,7 +1,7 @@ --- title: "Send Tokens" -description: "Send ETH or any ERC-20 token to an address, ENS name, basename, or cb.id using the Base Account MCP" -keywords: ["send tokens AI", "send USDC AI assistant", "send ETH AI", "Base Account MCP send", "ENS basename send AI"] +description: "Send ETH or any ERC-20 token to an address, ENS name, basename, or cb.id using Base MCP" +keywords: ["send tokens AI", "send USDC AI assistant", "send ETH AI", "Base MCP send", "ENS basename send AI"] --- import { TradeExecutionDemo } from "/snippets/TradeExecutionDemo.jsx" diff --git a/docs/ai-agents/guides/sign-messages.mdx b/docs/ai-agents/guides/sign-messages.mdx index 6bac6d967..4b3636c8a 100644 --- a/docs/ai-agents/guides/sign-messages.mdx +++ b/docs/ai-agents/guides/sign-messages.mdx @@ -1,7 +1,7 @@ --- title: "Sign Messages" -description: "Sign EIP-712 typed data and plain messages with your Base Account using the Base Account MCP" -keywords: ["sign message AI", "EIP-712 sign AI", "personal_sign AI", "Base Account MCP sign", "sign typed data AI assistant"] +description: "Sign EIP-712 typed data and plain messages with your Base Account using Base MCP" +keywords: ["sign message AI", "EIP-712 sign AI", "personal_sign AI", "Base MCP sign", "sign typed data AI assistant"] --- import { X402PayDemo } from "/snippets/x402PayDemo.jsx" @@ -35,7 +35,7 @@ Signing is usually invoked by protocols or integrations, not directly prompted b - Passes the message type and payload to the Base Account MCP. + Passes the message type and payload to Base MCP. Open `keys.coinbase.com` to review what you're signing — the message content is shown in full. diff --git a/docs/ai-agents/guides/swap-tokens.mdx b/docs/ai-agents/guides/swap-tokens.mdx index afeb0e880..cb186ef02 100644 --- a/docs/ai-agents/guides/swap-tokens.mdx +++ b/docs/ai-agents/guides/swap-tokens.mdx @@ -1,7 +1,7 @@ --- title: "Swap Tokens" -description: "Swap between any two tokens on Base via the Coinbase swap service using the Base Account MCP" -keywords: ["swap tokens AI", "token swap AI assistant", "USDC ETH swap AI", "Base Account MCP swap", "DeFi swap AI"] +description: "Swap between any two tokens on Base via the Coinbase swap service using Base MCP" +keywords: ["swap tokens AI", "token swap AI assistant", "USDC ETH swap AI", "Base MCP swap", "DeFi swap AI"] --- import { TradingQuickstartDemo } from "/snippets/TradingQuickstartDemo.jsx" diff --git a/docs/ai-agents/guides/view-history.mdx b/docs/ai-agents/guides/view-history.mdx index f517f3539..b5b3bd8fe 100644 --- a/docs/ai-agents/guides/view-history.mdx +++ b/docs/ai-agents/guides/view-history.mdx @@ -1,6 +1,6 @@ --- title: "View Transaction History" -description: "Browse past transactions, filter by asset, and paginate through your onchain history using the Base Account MCP" +description: "Browse past transactions, filter by asset, and paginate through your onchain history using Base MCP" keywords: ["transaction history AI", "get_transaction_history MCP", "Base wallet history AI", "onchain history AI assistant"] --- diff --git a/docs/ai-agents/index.mdx b/docs/ai-agents/index.mdx index e168fc504..866e39c8f 100644 --- a/docs/ai-agents/index.mdx +++ b/docs/ai-agents/index.mdx @@ -1,16 +1,16 @@ --- -title: "AI Agents on Base" -description: "Give your AI assistant a wallet. The Base Account MCP connects any AI to your Base Account — check balances, send funds, swap tokens, and sign messages." -keywords: ["Base Account MCP", "AI agent wallet", "mcp.base.org", "Base MCP", "AI assistant wallet", "onchain AI"] +title: "Base MCP" +description: "Give your AI assistant a wallet. Base MCP connects any AI to your Base Account — check balances, send funds, swap tokens, and sign messages." +keywords: ["Base MCP", "AI agent wallet", "mcp.base.org", "AI assistant wallet", "onchain AI"] --- -import { AgentPaymentDemo } from "/snippets/AgentPaymentDemo.jsx" +import { WalletSetupDemo } from "/snippets/WalletSetupDemo.jsx" -The Base Account MCP gives your AI assistant direct access to your [Base Account](https://base.org/account) — a smart wallet on Base. Connect once and your assistant can check balances, send funds, swap tokens, and sign messages. Every transaction requires your approval. +Base MCP gives your AI assistant direct access to your [Base Account](https://base.org/account) — a smart wallet on Base. Connect once and your assistant can check balances, send funds, swap tokens, and sign messages. Every transaction requires your approval. ## Demo - + ## How it works @@ -18,7 +18,7 @@ The Base Account MCP gives your AI assistant direct access to your [Base Account sequenceDiagram participant User participant AI as AI Assistant - participant MCP as Base Account MCP + participant MCP as Base MCP participant BA as Base Account participant Approve as keys.coinbase.com diff --git a/docs/ai-agents/payments.mdx b/docs/ai-agents/payments.mdx index 31d3d68ad..193031dbc 100644 --- a/docs/ai-agents/payments.mdx +++ b/docs/ai-agents/payments.mdx @@ -1,19 +1,19 @@ --- title: "Payments (x402)" description: "x402 payment protocol support for AI agents on Base" -keywords: ["x402 agent payments", "Base Account MCP x402", "CDP agentic wallet x402", "agent payments Base"] +keywords: ["x402 agent payments", "Base MCP x402", "CDP agentic wallet x402", "agent payments Base"] --- import { PaymentsQuickstartDemo } from "/snippets/PaymentsQuickstartDemo.jsx" -## x402 and the Base Account MCP +## x402 and Base MCP -The Base Account MCP supports sending and swapping tokens directly. **x402 payment protocol** — which lets agents pay for API access per-request in stablecoins — is not yet supported through the Base Account MCP. +Base MCP supports sending and swapping tokens directly. **x402 payment protocol** — which lets agents pay for API access per-request in stablecoins — is not yet supported through Base MCP. -x402 support for the Base Account MCP is coming soon. +x402 support for Base MCP is coming soon. ## For x402 payments today: CDP Agentic Wallet diff --git a/docs/ai-agents/plugins/morpho.mdx b/docs/ai-agents/plugins/morpho.mdx index c49c537bd..1aa961351 100644 --- a/docs/ai-agents/plugins/morpho.mdx +++ b/docs/ai-agents/plugins/morpho.mdx @@ -6,7 +6,7 @@ keywords: ["Morpho MCP", "Base lending AI", "Morpho vault agent", "mcp.morpho.or import { AcceptingPaymentsDemo } from "/snippets/AcceptingPaymentsDemo.jsx" -[Morpho](https://morpho.org) is a lending protocol on Base. The Morpho MCP server gives your assistant tools to query vaults, check markets, and prepare lending operations — which are then signed and sent through your Base Account MCP. +[Morpho](https://morpho.org) is a lending protocol on Base. The Morpho MCP server gives your assistant tools to query vaults, check markets, and prepare lending operations — which are then signed and sent through Base MCP. ## Demo @@ -21,7 +21,7 @@ sequenceDiagram participant User participant AI as AI Assistant participant Morpho as Morpho MCP - participant BA as Base Account MCP + participant BA as Base MCP User->>AI: "Deposit 100 USDC into the best vault" AI->>Morpho: morpho_query_vaults(asset=USDC, sortBy=APY) @@ -108,7 +108,7 @@ Add both MCPs to your assistant: ### Prepare (write via `send_calls`) -These tools return unsigned call data. Pass the result to Base Account MCP's `send_calls` to execute. +These tools return unsigned call data. Pass the result to Base MCP's `send_calls` to execute. | Tool | What it does | |------|-------------| @@ -165,7 +165,7 @@ Every Morpho write operation follows the same pattern: Call a `prepare_*` tool. Morpho simulates the operation and returns `{ calls, chainId }`. - Pass `calls` and `chainId` to Base Account MCP's `send_calls`. You'll get an `approvalUrl`. + Pass `calls` and `chainId` to Base MCP's `send_calls`. You'll get an `approvalUrl`. Open the `approvalUrl`, approve the transaction, then your assistant polls `get_request_status`. diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index 7a86f4859..de1f79ac9 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -1,7 +1,7 @@ --- title: "Quickstart" -description: "Connect the Base MCP to your AI assistant in under 2 minutes" -keywords: ["Base Account MCP quickstart", "mcp.base.org setup", "Claude Desktop MCP", "ChatGPT MCP", "Claude Code MCP wallet", "Cursor MCP", "VS Code MCP", "Windsurf MCP"] +description: "Connect Base MCP to your AI assistant in under 2 minutes" +keywords: ["Base MCP quickstart", "mcp.base.org setup", "Claude Desktop MCP", "ChatGPT MCP", "Claude Code MCP wallet", "Cursor MCP", "VS Code MCP", "Windsurf MCP"] --- import { WalletSetupDemo } from "/snippets/WalletSetupDemo.jsx" diff --git a/docs/ai-agents/setup/index.mdx b/docs/ai-agents/setup/index.mdx index 7110518de..8369e4961 100644 --- a/docs/ai-agents/setup/index.mdx +++ b/docs/ai-agents/setup/index.mdx @@ -1,12 +1,12 @@ --- title: "Setup" -description: "Connect the Base Account MCP to Claude Desktop, Claude.ai, ChatGPT, Claude Code, Cursor, VS Code, Windsurf, Zed, JetBrains, Le Chat, Warp, and more" -keywords: ["mcp.base.org setup", "Base Account MCP install", "Claude Desktop MCP config", "ChatGPT MCP connector", "Claude Code MCP", "Cursor MCP", "VS Code MCP", "Windsurf MCP", "Zed MCP", "JetBrains MCP"] +description: "Connect Base MCP to Claude Desktop, Claude.ai, ChatGPT, Claude Code, Cursor, VS Code, Windsurf, Zed, JetBrains, Le Chat, Warp, and more" +keywords: ["mcp.base.org setup", "Base MCP install", "Claude Desktop MCP config", "ChatGPT MCP connector", "Claude Code MCP", "Cursor MCP", "VS Code MCP", "Windsurf MCP", "Zed MCP", "JetBrains MCP"] --- import { X402PayDemo } from "/snippets/x402PayDemo.jsx" -The Base Account MCP server lives at `https://mcp.base.org`. Add it to your AI assistant once and your wallet tools are available in every conversation. +Base MCP lives at `https://mcp.base.org`. Add it to your AI assistant once and your wallet tools are available in every conversation. ## Authentication diff --git a/docs/ai-agents/skills/index.mdx b/docs/ai-agents/skills/index.mdx index 1b31135a1..7c6d67f02 100644 --- a/docs/ai-agents/skills/index.mdx +++ b/docs/ai-agents/skills/index.mdx @@ -1,6 +1,6 @@ --- title: "Skills" -description: "Install skills to give your AI coding assistant deep context on Base Account MCP tools and CDP Agentic Wallet capabilities" +description: "Install skills to give your AI coding assistant deep context on Base MCP tools and CDP Agentic Wallet capabilities" keywords: ["base-mcp skill", "CDP agentic wallet skill", "Base skills", "agent skills", "npx skills add base"] --- @@ -8,7 +8,7 @@ Skills are installable knowledge packs that give your AI coding assistant deep c ## base-mcp skill -The `base-mcp` skill gives your coding assistant full context on the Base Account MCP: all 9 tools, when to use them, approval mode patterns, and how to orchestrate with protocol plugins like Morpho. +The `base-mcp` skill gives your coding assistant full context on Base MCP: all 9 tools, when to use them, approval mode patterns, and how to orchestrate with protocol plugins like Morpho. ```bash Terminal npx skills add base/base-skills --skill base-mcp @@ -38,5 +38,5 @@ Includes `pay-for-service`, `search-for-service`, `monetize-service`, `send-usdc -x402 support for the Base Account MCP is coming soon. See [Payments](/ai-agents/payments) for details. +x402 support for Base MCP is coming soon. See [Payments](/ai-agents/payments) for details. diff --git a/docs/ai-agents/skills/payments/cdp-payment-skills.mdx b/docs/ai-agents/skills/payments/cdp-payment-skills.mdx index 70e271823..22de94614 100644 --- a/docs/ai-agents/skills/payments/cdp-payment-skills.mdx +++ b/docs/ai-agents/skills/payments/cdp-payment-skills.mdx @@ -7,7 +7,7 @@ keywords: ["CDP payment skills", "x402 skills", "pay-for-service skill", "search The CDP payment skills — included in the CDP Agentic Wallet bundle — give your agent the ability to discover x402-compatible APIs, pay for them per-request, and expose its own paid endpoints. -x402 support for the Base Account MCP is coming soon. Until then, these skills require the CDP Agentic Wallet. See [Payments](/ai-agents/payments) for context. +x402 support for Base MCP is coming soon. Until then, these skills require the CDP Agentic Wallet. See [Payments](/ai-agents/payments) for context. ## Install diff --git a/docs/ai-agents/skills/wallets/cdp-agentic-wallet.mdx b/docs/ai-agents/skills/wallets/cdp-agentic-wallet.mdx index f50e28564..a3cde1bec 100644 --- a/docs/ai-agents/skills/wallets/cdp-agentic-wallet.mdx +++ b/docs/ai-agents/skills/wallets/cdp-agentic-wallet.mdx @@ -7,7 +7,7 @@ keywords: ["CDP agentic wallet skill", "x402 agent wallet", "coinbase agentic wa The CDP Agentic Wallet is the recommended path for agents that need **x402 payment capabilities** — paying for API access per-request in stablecoins, or charging other agents for your services. -For wallet operations (sending, swapping, checking balances), use the [Base Account MCP](/ai-agents/quickstart) instead. CDP Agentic Wallet is specifically the right choice when you need x402 protocol support. +For wallet operations (sending, swapping, checking balances), use [Base MCP](/ai-agents/quickstart) instead. CDP Agentic Wallet is specifically the right choice when you need x402 protocol support. ## Install From 8918f9a08f23c74839d18e38092cc87b23736ece Mon Sep 17 00:00:00 2001 From: Youssef Date: Mon, 18 May 2026 23:59:01 +0100 Subject: [PATCH 06/36] update quickstart+morpho --- docs/ai-agents/plugins/morpho.mdx | 10 +- docs/ai-agents/quickstart.mdx | 430 +++++++++--------- docs/ai-agents/setup/index.mdx | 22 +- docs/snippets/AcceptingPaymentsDemo.jsx | 364 ++++++++++----- docs/snippets/AgentPaymentDemo.jsx | 552 ++++++++++------------- docs/snippets/AgentRegistrationDemo.jsx | 308 ++++++++++--- docs/snippets/AuthApprovalDemo.jsx | 204 +++++++++ docs/snippets/DataFetchingDemo.jsx | 341 +++++++++----- docs/snippets/PaymentsQuickstartDemo.jsx | 342 +++++++++----- docs/snippets/TradeExecutionDemo.jsx | 286 +++++++++--- docs/snippets/TradingQuickstartDemo.jsx | 315 ++++++++++--- docs/snippets/WalletSetupDemo.jsx | 9 +- docs/snippets/x402PayDemo.jsx | 287 +++++++++--- 13 files changed, 2288 insertions(+), 1182 deletions(-) create mode 100644 docs/snippets/AuthApprovalDemo.jsx diff --git a/docs/ai-agents/plugins/morpho.mdx b/docs/ai-agents/plugins/morpho.mdx index 1aa961351..96220dc1b 100644 --- a/docs/ai-agents/plugins/morpho.mdx +++ b/docs/ai-agents/plugins/morpho.mdx @@ -50,7 +50,7 @@ Add both MCPs to your assistant: ```json claude_desktop_config.json { "mcpServers": { - "base-account": { + "base": { "url": "https://mcp.base.org" }, "morpho": { @@ -62,13 +62,13 @@ Add both MCPs to your assistant: ```bash Terminal - claude mcp add --transport http base-account https://mcp.base.org + claude mcp add --transport http base https://mcp.base.org claude mcp add morpho --transport http https://mcp.morpho.org/ ``` ```toml codex.toml - [mcp_servers.base-account] + [mcp_servers.base] url = "https://mcp.base.org/" [mcp_servers.morpho] @@ -76,12 +76,12 @@ Add both MCPs to your assistant: ``` - Add a second entry alongside `base-account` in your MCP config: + Add a second entry alongside `base` in your MCP config: ```json { "mcpServers": { - "base-account": { "url": "https://mcp.base.org" }, + "base": { "url": "https://mcp.base.org" }, "morpho": { "url": "https://mcp.morpho.org/" } } } diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index de1f79ac9..3dab0d5ff 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -1,10 +1,11 @@ --- title: "Quickstart" description: "Connect Base MCP to your AI assistant in under 2 minutes" -keywords: ["Base MCP quickstart", "mcp.base.org setup", "Claude Desktop MCP", "ChatGPT MCP", "Claude Code MCP wallet", "Cursor MCP", "VS Code MCP", "Windsurf MCP"] +keywords: ["Base MCP quickstart", "mcp.base.org setup", "Claude Desktop MCP", "ChatGPT MCP", "Claude Code MCP wallet", "Cursor MCP", "Codex MCP", "Hermes MCP"] --- import { WalletSetupDemo } from "/snippets/WalletSetupDemo.jsx" +import { AuthApprovalDemo } from "/snippets/AuthApprovalDemo.jsx" Connect `mcp.base.org` to your AI assistant, then send your first prompt. @@ -12,239 +13,216 @@ Connect `mcp.base.org` to your AI assistant, then send your first prompt. -## Step 1 — Connect - - - - - Add to Claude - - - Paste `https://mcp.base.org` as the server URL and save. Works in Claude.ai (web, iOS, Android) and Claude Desktop. - - - Remote MCP integrations require a Claude Pro, Max, Team, or Enterprise plan. - - - **Claude Desktop config file** — if you prefer to configure manually, open **Settings → Developer → Edit Config** and add: - - | Platform | Config path | - |----------|-------------| - | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` | - | Windows | `%APPDATA%\Claude\claude_desktop_config.json` | - | Linux | `~/.config/Claude/claude_desktop_config.json` | - - ```json claude_desktop_config.json - { - "mcpServers": { - "base-account": { - "url": "https://mcp.base.org" +## Steps + + + + + + [![Add to Claude](https://img.shields.io/badge/Add%20to%20Claude-1F1F1F?style=for-the-badge)](https://claude.ai/customize/connectors?modal=add-custom-connector&connectorName=Base&connectorUrl=https%3A%2F%2Fmcp.base.org) + + Works in Claude.ai (web, iOS, Android) and Claude Desktop. Click the button above, or: + + 1. Open **Settings → Connectors → Add custom connector** + 2. The **Add custom connector** modal opens + 3. Fill in: + - **Name**: `Base` + - **Remote MCP server URL**: `https://mcp.base.org` + 4. Click **Add** + + **Claude Desktop config file** — if you prefer to configure manually, open **Settings → Developer → Edit Config** and add: + + | Platform | Config path | + |----------|-------------| + | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` | + | Windows | `%APPDATA%\Claude\claude_desktop_config.json` | + | Linux | `~/.config/Claude/claude_desktop_config.json` | + + ```json claude_desktop_config.json + { + "mcpServers": { + "base": { + "url": "https://mcp.base.org" + } + } } - } - } - ``` - - Save and restart Claude Desktop. A wallet icon will appear in the toolbar when connected. - - - - Add to ChatGPT - - - Then: - - 1. Enable **Developer Mode** if prompted (under Advanced) - 2. Click **Add custom connector** - 3. Enter the server URL: + ``` + + Save and restart Claude Desktop. + + + [![Add to ChatGPT](https://img.shields.io/badge/Add%20to%20ChatGPT-1F1F1F?style=for-the-badge)](https://chatgpt.com/#settings/Connectors) + + Click the button above, or open **Settings → Connectors** manually. Then: + + 1. Enable **Developer Mode** if prompted (under Advanced) + 2. Click **Create** to open the **New App** modal + 3. Fill in: + - **Name**: `Base` + - **Description** (optional): `Wallet and onchain tools for Base` + - **MCP Server URL**: `https://mcp.base.org` + - **Authentication**: `OAuth` + 4. Check **I understand and want to continue** on the risk warning + 5. Click **Create** + + ChatGPT will prompt you to authorize when you first use a wallet tool. + + + Run this in your terminal to add the server to the current project: + + ```bash Terminal + claude mcp add --transport http base https://mcp.base.org + ``` + + To install globally (available across all your projects): + + ```bash Terminal + claude mcp add --transport http --scope user base https://mcp.base.org + ``` + + Verify it connected: + + ```bash Terminal + claude mcp list + ``` + + The `base` server will show with a tool count once active. You can also run `/mcp` inside a Claude Code session to see server status. + + + ```bash Terminal + codex mcp add base --url https://mcp.base.org/ + ``` + + Or add to your `codex.toml`: + + ```toml codex.toml + [mcp_servers.base] + url = "https://mcp.base.org/" + ``` + + + [![Add to Cursor](https://img.shields.io/badge/Add%20to%20Cursor-1F1F1F?style=for-the-badge)](cursor://anysphere.cursor-deeplink/mcp/install?name=base&config=eyJ1cmwiOiJodHRwczovL21jcC5iYXNlLm9yZyJ9) + + Or add manually to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project): + + ```json mcp.json + { + "mcpServers": { + "base": { + "url": "https://mcp.base.org" + } + } + } + ``` + + Restart Cursor, then open **Settings → MCP** to confirm `base` shows as active. + + + Hand the agent this quickstart and let it install itself: + + ```text Prompt + Install the Base MCP server from https://docs.base.org/ai-agents/quickstart + ``` + + Hermes will fetch the page, write the entry to `~/.hermes/config.yaml`, and reload — no manual editing needed. + + **Manual install** — if you'd rather edit the config yourself: + + ```yaml ~/.hermes/config.yaml + mcp_servers: + base: + url: "https://mcp.base.org" + ``` + + Then start a Hermes chat (or run `/reload-mcp` inside an existing session) and Hermes will discover the tools automatically. + + + + + + + The `base-mcp` skill extends your assistant with pre-built prompts and workflows for wallet operations, token transfers, and DeFi interactions on Base. + + + + [![Download for Claude](https://img.shields.io/badge/Download%20skill-1F1F1F?style=for-the-badge&logo=download&logoColor=white)](https://github.com/base/skills/releases/download/base-mcp-v0.1.0/base-mcp.zip) + + 1. Click the button above to download `base-mcp.zip` + 2. In Claude Desktop or Claude.ai, open **Settings → Capabilities → Skills** + 3. Click **Upload skill** and select the downloaded `base-mcp.zip` + 4. Toggle the skill on + + Claude activates the skill automatically when relevant to your prompt. See [Use skills in Claude](https://support.claude.com/en/articles/12512180-use-skills-in-claude) for details. + + + [![Download for ChatGPT](https://img.shields.io/badge/Download%20skill-1F1F1F?style=for-the-badge&logo=download&logoColor=white)](https://github.com/base/skills/releases/download/base-mcp-v0.1.0/base-mcp.zip) + + 1. Click the button above to download `base-mcp.zip` + 2. In ChatGPT, open **Settings → Skills** + 3. Click **Add skill** and upload the downloaded `base-mcp.zip` + 4. Enable the skill for the conversations where you want it active + + See [Skills in ChatGPT](https://help.openai.com/en/articles/20001066-skills-in-chatgpt) for details. + + + Install the skill to your global skills directory: + + ```bash Terminal + curl -o ~/.claude/skills/base-mcp.md \ + https://raw.githubusercontent.com/base/skills/main/base-mcp.md + ``` + + The skill loads automatically in your next session. Invoke it with `/base-mcp` inside any Claude Code conversation. + + + Install from the community skill registry: + + ```bash Terminal + $skill-installer base-mcp + ``` + + + Add the skill as a global Cursor rule: + + ```bash Terminal + curl -o ~/.cursor/rules/base-mcp.mdc \ + https://raw.githubusercontent.com/base/skills/main/base-mcp.mdc + ``` + + + Install the skill to your Hermes skills directory: + + ```bash Terminal + curl -o ~/.hermes/skills/base-mcp.md \ + https://raw.githubusercontent.com/base/skills/main/base-mcp.md + ``` + + + + + + The first time you call a wallet tool, your assistant opens an auth modal at `keys.coinbase.com` to connect your Base Account. Click **Allow** once to authorize: + + + + Then ask your assistant: ```text - https://mcp.base.org + Show me my wallets ``` - 4. Save. ChatGPT will prompt you to authorize when you first use a wallet tool. - - - MCP connectors require a ChatGPT Plus or Pro plan. - - - - Run this in your terminal to add the server to the current project: - - ```bash Terminal - claude mcp add --transport http base-account https://mcp.base.org - ``` - - To install globally (available across all your projects): - - ```bash Terminal - claude mcp add --transport http --scope user base-account https://mcp.base.org - ``` - - Verify it connected: - - ```bash Terminal - claude mcp list - ``` - - The `base-account` server will show with a tool count once active. You can also run `/mcp` inside a Claude Code session to see server status. - - - ```bash Terminal - codex mcp add base-account --url https://mcp.base.org/ - ``` - - Or add to your `codex.toml`: - - ```toml codex.toml - [mcp_servers.base-account] - url = "https://mcp.base.org/" - ``` - - - - Add to Cursor - - - Or add manually to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project): - - ```json mcp.json - { - "mcpServers": { - "base-account": { - "url": "https://mcp.base.org" - } - } - } - ``` - - Restart Cursor, then open **Settings → MCP** to confirm `base-account` shows as active. - - - - Add to VS Code - - - Or add manually to `.vscode/mcp.json` (workspace) or your user MCP settings: - - ```json .vscode/mcp.json - { - "servers": { - "base-account": { - "type": "http", - "url": "https://mcp.base.org" - } - } - } + ```text + What's my USDC balance on Base? ``` - Open **Copilot Chat** in agent mode and confirm the wallet tools appear in the tool picker. - - - Add to `~/.codeium/windsurf/mcp_config.json`: - - ```json mcp_config.json - { - "mcpServers": { - "base-account": { - "url": "https://mcp.base.org" - } - } - } + ```text + Send 1 USDC to jesse.base.eth ``` - Restart Windsurf. Open **Cascade** — the MCP tools will be available once connected. - - - You can also add MCP servers from the UI: open **Cascade** → click the **hammer icon** → **Add MCP Server**. - - - - - - **Other clients** — Any MCP client that supports remote HTTP (Streamable HTTP) servers works with `https://mcp.base.org`. See the [setup guide](/ai-agents/setup) for Zed, JetBrains, Le Chat (Mistral), Warp, and others. On mobile, the Claude connector above works in the iOS and Android apps. - - -## Step 2 — Authorize - -The first time you use a wallet tool, your assistant will redirect you to `keys.coinbase.com` to connect your Base Account. You'll need a Coinbase account. Once authorized, all transactions still require individual approval at that same URL. - -## Step 3 — Try it - -Ask your assistant: - -```text -Show me my wallets -``` - -```text -What's my USDC balance on Base? -``` - -```text -Send 1 USDC to vitalik.base.eth -``` - -Every send, swap, or sign operation will give you an approval link. Open it, review the transaction, and confirm. - ---- - -## Add a plugin — Morpho lending - -Morpho lets your assistant query vaults, check APYs, and execute lending operations on Base — then sign them through your Base Account. - -Add both MCPs to your config: - - - - ```json claude_desktop_config.json - { - "mcpServers": { - "base-account": { - "url": "https://mcp.base.org" - }, - "morpho": { - "url": "https://mcp.morpho.org/" - } - } - } - ``` - - - ```bash Terminal - claude mcp add --transport http base-account https://mcp.base.org - claude mcp add morpho --transport http https://mcp.morpho.org/ + ```text + Find the best USDC vault on Base by APY and deposit 100 USDC ``` - - - Add a second entry alongside `base-account`: - ```json - "morpho": { "url": "https://mcp.morpho.org/" } - ``` - - - -Then try: - -```text -Find the best USDC vault on Base by APY and deposit 100 USDC -``` - -Morpho prepares the transaction; your Base Account signs it. See [Morpho plugin →](/ai-agents/plugins/morpho) - -## Next steps - - - - Step-by-step guides for sending, swapping, checking balance, and more. - - - Query vaults, check APYs, and execute lending operations on Base. - - - Detailed platform setup, auth flow, and approval mode explained. - - - Install the base-mcp skill for your coding assistant. - - + Every send, swap, or sign operation will give you an approval link. Open it, review the transaction, and confirm. + + diff --git a/docs/ai-agents/setup/index.mdx b/docs/ai-agents/setup/index.mdx index 8369e4961..971ee8f80 100644 --- a/docs/ai-agents/setup/index.mdx +++ b/docs/ai-agents/setup/index.mdx @@ -37,7 +37,7 @@ Click the button above to open the connector settings directly, paste `https://m ```json claude_desktop_config.json { "mcpServers": { - "base-account": { + "base": { "url": "https://mcp.base.org" } } @@ -66,13 +66,13 @@ On first use, ChatGPT will prompt you to authorize your Coinbase account. ### Claude Code ```bash Terminal -claude mcp add --transport http base-account https://mcp.base.org +claude mcp add --transport http base https://mcp.base.org ``` This writes to your project's `.claude/settings.json`. To add globally (all projects): ```bash Terminal -claude mcp add --transport http --scope user base-account https://mcp.base.org +claude mcp add --transport http --scope user base https://mcp.base.org ``` Verify the connection: @@ -86,13 +86,13 @@ claude mcp list ### Codex ```bash Terminal -codex mcp add base-account --url https://mcp.base.org/ +codex mcp add base --url https://mcp.base.org/ ``` Or add to `codex.toml`: ```toml codex.toml -[mcp_servers.base-account] +[mcp_servers.base] url = "https://mcp.base.org/" ``` @@ -100,7 +100,7 @@ url = "https://mcp.base.org/" ### Cursor - + Add to Cursor @@ -109,7 +109,7 @@ Or add manually to `~/.cursor/mcp.json`: ```json ~/.cursor/mcp.json { "mcpServers": { - "base-account": { + "base": { "url": "https://mcp.base.org" } } @@ -120,7 +120,7 @@ Or add manually to `~/.cursor/mcp.json`: ### VS Code - + Add to VS Code @@ -129,7 +129,7 @@ Or add to your VS Code MCP settings: ```json settings.json { "servers": { - "base-account": { + "base": { "type": "http", "url": "https://mcp.base.org" } @@ -146,7 +146,7 @@ Add to `~/.codeium/windsurf/mcp_config.json`: ```json mcp_config.json { "mcpServers": { - "base-account": { + "base": { "url": "https://mcp.base.org" } } @@ -164,7 +164,7 @@ Add to your Zed `settings.json` (`~/.config/zed/settings.json` on macOS/Linux, ` ```json settings.json { "context_servers": { - "base-account": { + "base": { "source": "custom", "command": { "path": "npx", diff --git a/docs/snippets/AcceptingPaymentsDemo.jsx b/docs/snippets/AcceptingPaymentsDemo.jsx index 416ec8129..a177932d2 100644 --- a/docs/snippets/AcceptingPaymentsDemo.jsx +++ b/docs/snippets/AcceptingPaymentsDemo.jsx @@ -1,138 +1,266 @@ -import { useState, useEffect, useRef } from "react"; -// Morpho plugin orchestration demo — used in plugins/morpho.mdx export const AcceptingPaymentsDemo = () => { - const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", - warn: "#fb923c", + const sans = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"; + const serif = "'Tiempos Headline','Iowan Old Style','Source Serif Pro',ui-serif,Georgia,serif"; + const mono = "ui-monospace,'SF Mono','Cascadia Code',Menlo,Monaco,Consolas,monospace"; + + const c = { + bg: "#1f1e1d", header: "#262624", border: "#34322f", inputBg: "#2a2926", + text: "#f5f4ed", body: "#e8e4dc", muted: "#a8a39d", dim: "#6b6663", + accent: "#D97757", bubble: "#2c2b28", bubbleText: "#f5f4ed", + code: "#e89972", codeBg: "rgba(217,119,87,0.12)", + toolBg: "#272622", toolBorder: "#3a3835", success: "#a3c585", }; - const steps = [ - { delay: 400, left: [{ t: "> Find the best USDC vault on Base and deposit 100 USDC", c: "active" }], right: [ - { t: "── morpho_query_vaults ──────────────────", c: "dim" }, - { t: " asset: USDC", c: "muted" }, - { t: " sortBy: APY", c: "muted" }, - ]}, - { delay: 700, left: [{ t: " ← top vault: Morpho Flagship USDC", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: " Morpho Flagship USDC", c: "success" }, - { t: " APY: 8.42% TVL: $42.1M", c: "success" }, - { t: " address: 0x8eB6...4Fa1", c: "code" }, - ]}, - { delay: 500, left: [{ t: "> prepare_deposit(vault, 100 USDC)", c: "active" }], right: [ - { t: "", c: "dim" }, - { t: "── morpho_prepare_deposit ───────────────", c: "dim" }, - { t: " Simulating deposit...", c: "muted" }, - ]}, - { delay: 700, left: [{ t: " ← simulation ok · calls ready", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "{", c: "code" }, - { t: ' "chainId": "0x2105",', c: "code" }, - { t: ' "calls": [approve, deposit]', c: "code" }, - { t: "}", c: "code" }, - ]}, - { delay: 500, left: [{ t: "> send_calls(chainId, calls)", c: "active" }], right: [ - { t: "", c: "dim" }, - { t: "── send_calls ──────────────────────────", c: "dim" }, - { t: " Submitting to Base Account MCP...", c: "muted" }, - ]}, - { delay: 600, left: [{ t: " ← approval required", c: "warn" }], right: [ - { t: "", c: "dim" }, - { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, - { t: ' requestId: "req_xyz789"', c: "muted" }, - ]}, - { delay: 500, left: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }], right: [] }, - { delay: 1000, left: [{ t: " ← user approved ✓", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── get_request_status ──────────────────", c: "dim" }, - { t: ' status: "confirmed"', c: "success" }, - ]}, - { delay: 400, left: [{ t: " ✓ 100 USDC deposited · earning 8.42% APY", c: "success" }], right: [] }, + const examples = [ + { + prompt: "Find the best USDC vault on Base and deposit 100 USDC", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "morpho", action: "list_vaults", args: { asset: "USDC", chain: "base", sortBy: "APY" } } }, + { delay: 500, type: "text", text: "Steakhouse USDC has the best yield. Preparing deposit via send_calls..." }, + { delay: 300, type: "rows", rows: [ + { token: "Morpho · Steakhouse USDC", amount: "8.42% APY", value: "$24.1M TVL · winner" }, + { token: "Morpho · Re7 USDC", amount: "7.91% APY", value: "$18.7M TVL" }, + { token: "Morpho · Flagship USDC", amount: "7.34% APY", value: "$42.1M TVL" }, + ]}, + { delay: 500, type: "tool", tool: { server: "morpho", action: "prepare_deposit", args: { vault: "Steakhouse USDC", amount: "100 USDC" } } }, + { delay: 350, type: "tool", tool: { server: "base-account", action: "send_calls", args: { chainId: "0x2105", calls: "[approve, deposit]" } } }, + { delay: 450, type: "approval", url: "keys.coinbase.com/approve/req_b9f2a1" }, + { delay: 1100, type: "confirm", text: "Deposited 100 USDC into Steakhouse USDC · earning 8.42% APY" }, + ], + }, + { + prompt: "Supply 0.5 ETH as collateral and borrow 1000 USDC", + events: [ + { delay: 380, type: "thinking" }, + { delay: 550, type: "tool", tool: { server: "morpho", action: "get_market", args: { collateral: "ETH", loan: "USDC", chain: "base" } } }, + { delay: 500, type: "text", text: "Found Morpho ETH/USDC market on Base. Batching supply + borrow..." }, + { delay: 500, type: "tool", tool: { server: "morpho", action: "prepare_supply_collateral", args: { asset: "ETH", amount: "0.5", borrow: "1000 USDC" } } }, + { delay: 350, type: "tool", tool: { server: "base-account", action: "send_calls", args: { chainId: "0x2105", calls: "[supplyCollateral, borrow]" } } }, + { delay: 450, type: "approval", url: "keys.coinbase.com/approve/req_m3k2p9" }, + { delay: 1100, type: "confirm", text: "Supplied 0.5 ETH · borrowed 1000 USDC · health factor 2.1" }, + ], + }, + { + prompt: "Repay all my Morpho USDC debt", + events: [ + { delay: 380, type: "thinking" }, + { delay: 550, type: "tool", tool: { server: "morpho", action: "get_position", args: { market: "ETH/USDC", chain: "base" } } }, + { delay: 500, type: "text", text: "You owe 1002.14 USDC including accrued interest. Preparing full repayment..." }, + { delay: 500, type: "tool", tool: { server: "morpho", action: "prepare_repay", args: { amount: "1002.14 USDC", market: "ETH/USDC" } } }, + { delay: 350, type: "tool", tool: { server: "base-account", action: "send_calls", args: { chainId: "0x2105", calls: "[approve, repayAll]" } } }, + { delay: 450, type: "approval", url: "keys.coinbase.com/approve/req_r7d4s1" }, + { delay: 1100, type: "confirm", text: "Repaid 1002.14 USDC · Morpho position closed" }, + ], + }, ]; - const [leftLines, setLeftLines] = useState([]); - const [rightLines, setRightLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const leftRef = useRef(null); - const rightRef = useRef(null); - - useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); - useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); - useEffect(() => { if (rightRef.current) rightRef.current.scrollTop = rightRef.current.scrollHeight; }, [rightLines]); - - const reset = () => { setLeftLines([]); setRightLines([]); setRunning(false); setDone(false); }; - - const run = () => { - if (running || done) return; - setRunning(true); - let i = 0; - const next = () => { - if (i >= steps.length) { setRunning(false); setDone(true); return; } - const s = steps[i]; - setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; next(); - }, s.delay); - }; - next(); + const [activeIdx, setActiveIdx] = useState(null); + const [eventIdx, setEventIdx] = useState(0); + const scrollRef = useRef(null); + const timersRef = useRef([]); + + const clearTimers = () => { timersRef.current.forEach(clearTimeout); timersRef.current = []; }; + + useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [eventIdx, activeIdx]); + useEffect(() => () => clearTimers(), []); + + const pick = (idx) => { + if (activeIdx !== null) return; + setActiveIdx(idx); + setEventIdx(0); + clearTimers(); + let cumulative = 0; + examples[idx].events.forEach((e, i) => { + cumulative += e.delay; + timersRef.current.push(setTimeout(() => setEventIdx(i + 1), cumulative)); + }); }; - const renderLine = (item, i) => { - if (!item.t) return
; - return
{item.t}
; + const reset = () => { clearTimers(); setActiveIdx(null); setEventIdx(0); }; + const ex = activeIdx !== null ? examples[activeIdx] : null; + + const TrafficLights = () => ( +
+ + + +
+ ); + + const UserBubble = ({ children }) => ( +
+
{children}
+
+ ); + + const ToolCall = ({ tool, completed }) => ( +
+
+ + {completed + ? + : } + + + {tool.server} + · + {tool.action} + ( + {Object.entries(tool.args).map(([k, v], i, arr) => ( + {k}: "{v}"{i < arr.length - 1 && , } + ))} + ) + +
+
+ ); + + const Thinking = () => ( +
+ + {[0, 1, 2].map(i => )} + + Thinking +
+ ); + + const ResponseText = ({ children, top }) => ( +
{children}
+ ); + + const ResponseRows = ({ rows }) => ( +
+ {rows.map((r, i) => ( +
+ + {r.token} + {r.amount} + {r.value} +
+ ))} +
+ ); + + const ApprovalLink = ({ url }) => ( +
+ + + {url} + +
+ ); + + const Confirm = ({ text }) => ( +
+ + {text} +
+ ); + + const ChipBtn = ({ onClick, children }) => { + const [hover, setHover] = useState(false); + return ( + + ); + }; + + const renderEvents = () => { + if (!ex) return null; + const shown = ex.events.slice(0, eventIdx); + return shown.map((event, i) => { + if (event.type === "thinking") { + if (i < shown.length - 1) return null; + return ; + } + if (event.type === "tool") { + const hasLater = shown.slice(i + 1).some(e => e.type !== "thinking"); + return ; + } + if (event.type === "text") return {event.text}; + if (event.type === "rows") return ; + if (event.type === "approval") return ; + if (event.type === "confirm") return ; + return null; + }); }; return ( -
-
-
- {">"}_ -
- Morpho + Base Account MCP +
+ + +
+ + Morpho + Base MCP +
- + {activeIdx !== null && ( + + )}
-
-
-
- Agent -
-
- {leftLines.map(renderLine)} - {running &&
{"▋"}
} + +
+ {!ex && ( +
+
+ Try asking once mcp.base.org and mcp.morpho.org are connected: +
+
+ {examples.map((e, i) => pick(i)}>{e.prompt})} +
+ )} + {ex && <>{ex.prompt}{renderEvents()}} +
+ +
+
+ + Write a message... + Sonnet 4.6 +
-
-
- MCP Response -
-
- {rightLines.map(renderLine)} -
+
+ Demo · Morpho prepares calls, Base Account signs them
-
- {!running && !done && leftLines.length === 0 && ( - - )} - {done && ( - - )} -
); }; diff --git a/docs/snippets/AgentPaymentDemo.jsx b/docs/snippets/AgentPaymentDemo.jsx index a21b0772b..e2a4ad929 100644 --- a/docs/snippets/AgentPaymentDemo.jsx +++ b/docs/snippets/AgentPaymentDemo.jsx @@ -1,361 +1,261 @@ -import { useState, useEffect, useRef } from "react"; export const AgentPaymentDemo = () => { - const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", - warn: "#fb923c", + const sans = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"; + const serif = "'Tiempos Headline','Iowan Old Style','Source Serif Pro',ui-serif,Georgia,serif"; + const mono = "ui-monospace,'SF Mono','Cascadia Code',Menlo,Monaco,Consolas,monospace"; + + const c = { + bg: "#1f1e1d", header: "#262624", border: "#34322f", inputBg: "#2a2926", + text: "#f5f4ed", body: "#e8e4dc", muted: "#a8a39d", dim: "#6b6663", + accent: "#D97757", bubble: "#2c2b28", bubbleText: "#f5f4ed", + code: "#e89972", codeBg: "rgba(217,119,87,0.12)", + toolBg: "#272622", toolBorder: "#3a3835", success: "#a3c585", }; - const flows = { - // Tab 0 — Connect: platform choice - connect_claude: [ - { delay: 400, left: [{ t: "> claude mcp add --transport http base-account https://mcp.base.org", c: "active" }], right: [ - { t: "── .claude/settings.json ───────────────", c: "dim" }, - { t: "{", c: "code" }, - ]}, - { delay: 650, left: [{ t: " ✓ MCP server added: base-account", c: "success" }], right: [ - { t: ' "mcpServers": {', c: "code" }, - { t: ' "base-account": {', c: "code" }, - { t: ' "url": "https://mcp.base.org"', c: "code" }, - { t: " }", c: "code" }, - { t: " }", c: "code" }, - { t: "}", c: "code" }, - ]}, - { delay: 600, left: [{ t: "> Show me my wallets", c: "active" }], right: [] }, - { delay: 500, left: [{ t: " ← Authorizing via keys.coinbase.com...", c: "warn" }], right: [ - { t: "", c: "dim" }, - { t: "── OAuth ───────────────────────────────", c: "dim" }, - { t: " → keys.coinbase.com/authorize", c: "warn" }, - ]}, - { delay: 800, left: [{ t: " ✓ Base Account connected 0x4a3f...b7c1", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: ' address: "0x4a3f...b7c1"', c: "success" }, - { t: ' network: "base-mainnet"', c: "success" }, - { t: ' status: "ready"', c: "success" }, - ]}, - ], - connect_desktop: [ - { delay: 400, left: [{ t: "> Edit claude_desktop_config.json", c: "active" }], right: [ - { t: "── claude_desktop_config.json ──────────", c: "dim" }, - { t: "{", c: "code" }, - ]}, - { delay: 600, left: [{ t: " Adding base-account entry...", c: "muted" }], right: [ - { t: ' "mcpServers": {', c: "code" }, - { t: ' "base-account": {', c: "code" }, - { t: ' "url": "https://mcp.base.org"', c: "code" }, - { t: " }", c: "code" }, - { t: " }", c: "code" }, - { t: "}", c: "code" }, - ]}, - { delay: 550, left: [{ t: " Restart Claude Desktop →", c: "muted" }], right: [] }, - { delay: 700, left: [{ t: " ✓ base-account MCP connected", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── toolbar ─────────────────────────────", c: "dim" }, - { t: " [🔵 base-account] connected", c: "success" }, - ]}, - ], - connect_chatgpt: [ - { delay: 400, left: [{ t: "> Settings → Connectors → Add MCP", c: "active" }], right: [ - { t: "── ChatGPT Connectors ───────────────────", c: "dim" }, - { t: " Add custom connector", c: "muted" }, - ]}, - { delay: 550, left: [{ t: " Enter: https://mcp.base.org", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: " Server URL:", c: "muted" }, - { t: " https://mcp.base.org [Save]", c: "active" }, - ]}, - { delay: 700, left: [{ t: " ✓ Base Account MCP saved", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── Connectors ──────────────────────────", c: "dim" }, - { t: " ✓ base-account mcp.base.org", c: "success" }, - ]}, - ], + const examples = [ + { + prompt: "Show me my wallets", + events: [ + { delay: 380, type: "thinking" }, + { delay: 550, type: "tool", tool: { server: "base-account", action: "get_wallets", args: {} } }, + { delay: 600, type: "text", text: "You have 2 wallets connected to Base MCP:" }, + { delay: 250, type: "rows", rows: [ + { token: "Base Account", amount: "0x4a3f…b7c1", value: "in session · approval mode" }, + { token: "Agent Wallet", amount: "0x9c2d…e4f8", value: "not in session" }, + ]}, + { delay: 400, type: "confirm", text: "Connected · ready to send, swap, and sign" }, + ], + }, + { + prompt: "What's my USDC balance on Base?", + events: [ + { delay: 380, type: "thinking" }, + { delay: 550, type: "tool", tool: { server: "base-account", action: "get_portfolio", args: { chain: "base" } } }, + { delay: 600, type: "text", text: "Your current portfolio on Base:" }, + { delay: 250, type: "rows", rows: [ + { token: "USDC", amount: "245.80", value: "$245.80" }, + { token: "ETH", amount: "0.0412", value: "$148.33" }, + { token: "WETH", amount: "0.0100", value: "$36.02" }, + ]}, + { delay: 400, type: "confirm", text: "Total: $430.15 on Base" }, + ], + }, + { + prompt: "Send 5 USDC to alice.base.eth", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "base-account", action: "send", args: { to: "alice.base.eth", asset: "USDC", amount: "5", chain: "base" } } }, + { delay: 500, type: "text", text: "Resolved alice.base.eth → 0x71C7…976F. Approve to send:" }, + { delay: 250, type: "approval", url: "keys.coinbase.com/approve/req_a4f7c2" }, + { delay: 1100, type: "confirm", text: "Sent 5 USDC to alice.base.eth" }, + ], + }, + ]; + + const [activeIdx, setActiveIdx] = useState(null); + const [eventIdx, setEventIdx] = useState(0); + const scrollRef = useRef(null); + const timersRef = useRef([]); - // Tab 1 — Wallets & Balances: linear - balances: [ - { delay: 400, left: [{ t: "> Show me my wallets", c: "active" }], right: [ - { t: "── get_wallets ─────────────────────────", c: "dim" }, - { t: "tool: get_wallets()", c: "muted" }, - ]}, - { delay: 650, left: [{ t: " ← 2 wallets", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: ' { type: "base-account",', c: "code" }, - { t: ' address: "0x4a3f...b7c1",', c: "code" }, - { t: ' inSession: true }', c: "code" }, - ]}, - { delay: 400, left: [{ t: " Base Account: 0x4a3f...b7c1", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: ' { type: "agent-wallet",', c: "code" }, - { t: ' address: "0x9c2d...e4f8",', c: "code" }, - { t: ' inSession: false }', c: "code" }, - ]}, - { delay: 600, left: [{ t: "> What's my balance on Base?", c: "active" }], right: [] }, - { delay: 500, left: [{ t: " ← get_portfolio(chain=base)", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "── get_portfolio ────────────────────────", c: "dim" }, - { t: " USDC 245.80 $245.80", c: "success" }, - { t: " ETH 0.0412 $148.33", c: "success" }, - { t: " WETH 0.0100 $36.02 ", c: "success" }, - ]}, - { delay: 400, left: [{ t: " Total: $430.15 on Base", c: "success" }], right: [] }, - ], + const clearTimers = () => { timersRef.current.forEach(clearTimeout); timersRef.current = []; }; - // Tab 2 — Send & Swap: choice - send: [ - { delay: 400, left: [{ t: "> Send 10 USDC to alice.base.eth", c: "active" }], right: [ - { t: "── send() ──────────────────────────────", c: "dim" }, - { t: " recipient: alice.base.eth", c: "muted" }, - { t: " amount: 10", c: "muted" }, - { t: " asset: USDC", c: "muted" }, - { t: " chain: base", c: "muted" }, - ]}, - { delay: 650, left: [{ t: " ← approval required", c: "warn" }], right: [ - { t: "", c: "dim" }, - { t: "── approval mode ────────────────────────", c: "warn" }, - { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, - { t: ' requestId: "req_abc123"', c: "muted" }, - ]}, - { delay: 500, left: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }], right: [] }, - { delay: 900, left: [{ t: " ← user approved ✓", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── get_request_status ──────────────────", c: "dim" }, - { t: ' status: "confirmed"', c: "success" }, - { t: ' txHash: "0xf7e3...9a12"', c: "success" }, - ]}, - { delay: 400, left: [{ t: " ✓ 10 USDC sent to alice.base.eth", c: "success" }], right: [] }, - ], - swap: [ - { delay: 400, left: [{ t: "> Swap 100 USDC for ETH on Base", c: "active" }], right: [ - { t: "── swap() ──────────────────────────────", c: "dim" }, - { t: " fromAsset: USDC", c: "muted" }, - { t: " toAsset: ETH", c: "muted" }, - { t: " amount: 100", c: "muted" }, - { t: " chain: base", c: "muted" }, - ]}, - { delay: 650, left: [{ t: " ← approval required", c: "warn" }], right: [ - { t: "", c: "dim" }, - { t: "── approval mode ────────────────────────", c: "warn" }, - { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, - { t: ' requestId: "req_def456"', c: "muted" }, - ]}, - { delay: 500, left: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }], right: [] }, - { delay: 900, left: [{ t: " ← user approved ✓", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── get_request_status ──────────────────", c: "dim" }, - { t: ' status: "confirmed"', c: "success" }, - { t: ' received: "0.03512 ETH"', c: "success" }, - ]}, - { delay: 400, left: [{ t: " ✓ received 0.03512 ETH", c: "success" }], right: [] }, - ], + useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [eventIdx, activeIdx]); + useEffect(() => () => clearTimers(), []); + + const pick = (idx) => { + if (activeIdx !== null) return; + setActiveIdx(idx); + setEventIdx(0); + clearTimers(); + let cumulative = 0; + examples[idx].events.forEach((e, i) => { + cumulative += e.delay; + timersRef.current.push(setTimeout(() => setEventIdx(i + 1), cumulative)); + }); }; - const tabs = ["Connect", "Wallets & Balances", "Send & Swap"]; - const rightLabels = ["Config", "MCP Response", "Approval Flow"]; - const intros = [ - "> Choose your platform:", - "> Checking your Base Account...", - "> Choose an action:", - ]; + const reset = () => { clearTimers(); setActiveIdx(null); setEventIdx(0); }; + const ex = activeIdx !== null ? examples[activeIdx] : null; - const [activeTab, setActiveTab] = useState(0); - const [choice1, setChoice1] = useState(null); - const [choice2, setChoice2] = useState(null); - const [leftLines, setLeftLines] = useState([]); - const [rightLines,setRightLines]= useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const leftRef = useRef(null); - const rightRef = useRef(null); + const TrafficLights = () => ( +
+ + + +
+ ); - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); + const UserBubble = ({ children }) => ( +
+
{children}
+
+ ); - useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); - useEffect(() => { if (rightRef.current) rightRef.current.scrollTop = rightRef.current.scrollHeight; }, [rightLines]); + const ToolCall = ({ tool, completed }) => ( +
+
+ + {completed + ? + : } + + + {tool.server} + · + {tool.action} + ( + {Object.entries(tool.args).map(([k, v], i, arr) => ( + {k}: "{v}"{i < arr.length - 1 && , } + ))} + ) + +
+
+ ); - const reset = (tab) => { - const next = tab !== undefined ? tab : activeTab; - setActiveTab(next); - setChoice1(null); - setChoice2(null); - setLeftLines([]); - setRightLines([]); - setRunning(false); - setDone(false); - }; + const Thinking = () => ( +
+ + {[0, 1, 2].map(i => )} + + Thinking +
+ ); - useEffect(() => { - setLeftLines([]); - setRightLines([]); - setChoice1(null); - setChoice2(null); - setRunning(false); - setDone(false); - const t = setTimeout(() => { - setLeftLines([{ t: intros[activeTab], c: "muted" }]); - // Tab 1 is linear — auto-start - if (activeTab === 1) { - setTimeout(() => animateFlow("balances"), 300); - } - }, 350); - return () => clearTimeout(t); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [activeTab]); + const ResponseText = ({ children, top }) => ( +
{children}
+ ); - const animateFlow = (key) => { - const steps = flows[key]; - if (!steps) return; - setRunning(true); - setDone(false); - let i = 0; - const next = () => { - if (i >= steps.length) { setRunning(false); setDone(true); return; } - const s = steps[i]; - setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); - }, s.delay); - }; - next(); - }; + const ResponseRows = ({ rows }) => ( +
+ {rows.map((r, i) => ( +
+ + {r.token} + {r.amount} + {r.value} +
+ ))} +
+ ); - const pickConnect = (p) => { - if (choice1) return; - setChoice1(p); - const labels = { claude: "Claude Code", desktop: "Claude Desktop", chatgpt: "ChatGPT" }; - setLeftLines(prev => [...prev, { t: " [" + labels[p] + "]", c: "active" }]); - setTimeout(() => animateFlow("connect_" + p), 150); - }; + const ApprovalLink = ({ url }) => ( +
+ + + {url} + +
+ ); - const pickAction = (a) => { - if (choice2) return; - setChoice2(a); - const labels = { send: "Send", swap: "Swap" }; - setLeftLines(prev => [...prev, { t: " [" + labels[a] + "]", c: "active" }]); - setTimeout(() => animateFlow(a), 150); - }; + const Confirm = ({ text }) => ( +
+ + {text} +
+ ); - const renderLine = (item, i) => { - if (!item.t) return
; + const ChipBtn = ({ onClick, children }) => { + const [hover, setHover] = useState(false); return ( -
- {item.t} -
+ ); }; - const btnBase = { - fontFamily: mono, fontSize: 12, - color: "#60a5fa", background: "transparent", - border: "1px solid #27272a", borderRadius: 4, - cursor: "pointer", padding: "1px 8px", - marginRight: 6, lineHeight: "20px", + const renderEvents = () => { + if (!ex) return null; + const shown = ex.events.slice(0, eventIdx); + return shown.map((event, i) => { + if (event.type === "thinking") { + if (i < shown.length - 1) return null; + return ; + } + if (event.type === "tool") { + const hasLater = shown.slice(i + 1).some(e => e.type !== "thinking"); + return ; + } + if (event.type === "text") return {event.text}; + if (event.type === "rows") return ; + if (event.type === "approval") return ; + if (event.type === "confirm") return ; + return null; + }); }; - const onBtnEnter = (e) => { e.currentTarget.style.color = "#e4e4e7"; e.currentTarget.style.background = "#1c1c1e"; e.currentTarget.style.borderColor = "#3f3f46"; }; - const onBtnLeave = (e) => { e.currentTarget.style.color = "#60a5fa"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "#27272a"; }; - - const showConnectBtns = activeTab === 0 && !choice1 && leftLines.length > 0; - const showActionBtns = activeTab === 2 && !choice2 && leftLines.length > 0; - const isLastTab = activeTab === 2; - const footerLabel = isLastTab ? "↺ Play again" : "Next: " + tabs[activeTab + 1] + " →"; return ( -
+
+ - {/* Tab bar */} -
-
- {">"}_ -
- {tabs.map((tab, i) => { - const active = i === activeTab; - return ( - - ); - })} +
+ + Base wallet +
- + {activeIdx !== null && ( + + )}
- {/* Split pane */} -
- {/* Left — Agent */} -
-
- Agent -
-
- {leftLines.map(renderLine)} - {showConnectBtns && ( -
- pick: - - - -
- )} - {showActionBtns && ( -
- pick: - - -
- )} - {running &&
{"▋"}
} -
-
- {/* Right — Config/Response */} -
-
- {rightLabels[activeTab]} -
-
- {rightLines.map(renderLine)} +
+ {!ex && ( +
+
+ Try asking your assistant once mcp.base.org is connected: +
+
+ {examples.map((e, i) => pick(i)}>{e.prompt})} +
-
+ )} + {ex && <>{ex.prompt}{renderEvents()}}
- {/* Footer */} -
- {done && ( - - )} + Write a message... + Sonnet 4.6 + +
+
+ Demo · Your assistant approves every transaction at keys.coinbase.com +
); diff --git a/docs/snippets/AgentRegistrationDemo.jsx b/docs/snippets/AgentRegistrationDemo.jsx index d62899ee4..ded00062d 100644 --- a/docs/snippets/AgentRegistrationDemo.jsx +++ b/docs/snippets/AgentRegistrationDemo.jsx @@ -1,82 +1,256 @@ -import { useState, useEffect, useRef } from "react"; export const AgentRegistrationDemo = () => { - const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8" }; - - const steps = [ - { delay: 400, lines: [{ t: "> Show my last 5 transactions on Base", c: "active" }] }, - { delay: 500, lines: [ - { t: " ── get_transaction_history ────────────────", c: "dim" }, - { t: " chain: base limit: 5", c: "muted" }, - ]}, - { delay: 700, lines: [ - { t: " send -10.00 USDC alice.base.eth 2min ago", c: "code" }, - { t: " swap -100.00 USDC +0.0351 ETH 1hr ago ", c: "code" }, - { t: " recv +50.00 USDC coinbase.com 3hr ago ", c: "success" }, - { t: " send -5.00 USDC bob.eth 1d ago ", c: "code" }, - { t: " recv +100.00 USDC 0x9f3a...2e01 2d ago ", c: "success" }, - ]}, - { delay: 500, lines: [{ t: "", c: "dim" }, { t: "> What's my current balance?", c: "active" }] }, - { delay: 500, lines: [ - { t: " ── get_portfolio ──────────────────────────", c: "dim" }, - ]}, - { delay: 650, lines: [ - { t: " USDC 280.80 $280.80", c: "success" }, - { t: " ETH 0.0763 $274.33", c: "success" }, - { t: " DEGEN 4820.00 $182.33", c: "success" }, - { t: " Total: $737.46 on Base", c: "success" }, - ]}, + const sans = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"; + const serif = "'Tiempos Headline','Iowan Old Style','Source Serif Pro',ui-serif,Georgia,serif"; + const mono = "ui-monospace,'SF Mono','Cascadia Code',Menlo,Monaco,Consolas,monospace"; + + const c = { + bg: "#1f1e1d", header: "#262624", border: "#34322f", inputBg: "#2a2926", + text: "#f5f4ed", body: "#e8e4dc", muted: "#a8a39d", dim: "#6b6663", + accent: "#D97757", bubble: "#2c2b28", bubbleText: "#f5f4ed", + code: "#e89972", codeBg: "rgba(217,119,87,0.12)", + toolBg: "#272622", toolBorder: "#3a3835", success: "#a3c585", + }; + + const examples = [ + { + prompt: "Show my last 5 transactions on Base", + events: [ + { delay: 380, type: "thinking" }, + { delay: 550, type: "tool", tool: { server: "base-account", action: "get_transaction_history", args: { chain: "base", limit: "5" } } }, + { delay: 600, type: "text", text: "Here are your 5 most recent transactions:" }, + { delay: 250, type: "rows", rows: [ + { token: "Sent 10 USDC", amount: "−$10.00", value: "alice.base.eth · 2 min ago" }, + { token: "Swapped", amount: "−$180.41", value: "100 USDC → 0.035 ETH · 1 hr ago" }, + { token: "Received USDC", amount: "+$50.00", value: "from coinbase.com · 3 hr ago" }, + { token: "Sent 5 USDC", amount: "−$5.00", value: "bob.eth · 1 day ago" }, + { token: "Received USDC", amount: "+$100.00", value: "from 0x9f3a…2e01 · 2 days ago" }, + ]}, + ], + }, + { + prompt: "Show all my USDC sends from the last week", + events: [ + { delay: 380, type: "thinking" }, + { delay: 550, type: "tool", tool: { server: "base-account", action: "get_transaction_history", args: { asset: "USDC", type: "send", limit: "10" } } }, + { delay: 600, type: "text", text: "3 USDC sends in the last 7 days:" }, + { delay: 250, type: "rows", rows: [ + { token: "alice.base.eth", amount: "−10 USDC", value: "2 min ago" }, + { token: "bob.eth", amount: "−5 USDC", value: "1 day ago" }, + { token: "marketplace.base", amount: "−25 USDC", value: "3 days ago" }, + ]}, + { delay: 400, type: "confirm", text: "Total sent: 40 USDC over 3 transactions" }, + ], + }, + { + prompt: "What did I receive this month?", + events: [ + { delay: 380, type: "thinking" }, + { delay: 550, type: "tool", tool: { server: "base-account", action: "get_transaction_history", args: { type: "receive", limit: "50" } } }, + { delay: 600, type: "text", text: "You received funds across 4 transactions this month:" }, + { delay: 250, type: "rows", rows: [ + { token: "coinbase.com", amount: "+150 USDC", value: "3 hr ago" }, + { token: "0x9f3a…2e01", amount: "+100 USDC", value: "2 days ago" }, + { token: "merchant.base", amount: "+27.40 USDC", value: "5 days ago" }, + { token: "friend.base", amount: "+25 USDC", value: "8 days ago" }, + ]}, + { delay: 400, type: "confirm", text: "Total received: 302.40 USDC this month" }, + ], + }, ]; - const [lines, setLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const ref = useRef(null); - - useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); - useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]); - - const reset = () => { setLines([]); setRunning(false); setDone(false); }; - const run = () => { - if (running || done) return; - setRunning(true); - let i = 0; - const next = () => { - if (i >= steps.length) { setRunning(false); setDone(true); return; } - setTimeout(() => { setLines(p => [...p, ...steps[i].lines]); i++; next(); }, steps[i].delay); - }; - next(); + const [activeIdx, setActiveIdx] = useState(null); + const [eventIdx, setEventIdx] = useState(0); + const scrollRef = useRef(null); + const timersRef = useRef([]); + + const clearTimers = () => { timersRef.current.forEach(clearTimeout); timersRef.current = []; }; + + useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [eventIdx, activeIdx]); + useEffect(() => () => clearTimers(), []); + + const pick = (idx) => { + if (activeIdx !== null) return; + setActiveIdx(idx); + setEventIdx(0); + clearTimers(); + let cumulative = 0; + examples[idx].events.forEach((e, i) => { + cumulative += e.delay; + timersRef.current.push(setTimeout(() => setEventIdx(i + 1), cumulative)); + }); + }; + + const reset = () => { clearTimers(); setActiveIdx(null); setEventIdx(0); }; + const ex = activeIdx !== null ? examples[activeIdx] : null; + + const TrafficLights = () => ( +
+ + + +
+ ); + + const UserBubble = ({ children }) => ( +
+
{children}
+
+ ); + + const ToolCall = ({ tool, completed }) => ( +
+
+ + {completed + ? + : } + + + {tool.server} + · + {tool.action} + ( + {Object.entries(tool.args).map(([k, v], i, arr) => ( + {k}: "{v}"{i < arr.length - 1 && , } + ))} + ) + +
+
+ ); + + const Thinking = () => ( +
+ + {[0, 1, 2].map(i => )} + + Thinking +
+ ); + + const ResponseText = ({ children, top }) => ( +
{children}
+ ); + + const ResponseRows = ({ rows }) => ( +
+ {rows.map((r, i) => ( +
+ + {r.token} + {r.amount} + {r.value} +
+ ))} +
+ ); + + const Confirm = ({ text }) => ( +
+ + {text} +
+ ); + + const ChipBtn = ({ onClick, children }) => { + const [hover, setHover] = useState(false); + return ( + + ); }; - const renderLine = (item, i) => { - if (!item.t) return
; - return
{item.t}
; + const renderEvents = () => { + if (!ex) return null; + const shown = ex.events.slice(0, eventIdx); + return shown.map((event, i) => { + if (event.type === "thinking") { + if (i < shown.length - 1) return null; + return ; + } + if (event.type === "tool") { + const hasLater = shown.slice(i + 1).some(e => e.type !== "thinking"); + return ; + } + if (event.type === "text") return {event.text}; + if (event.type === "rows") return ; + if (event.type === "confirm") return ; + return null; + }); }; return ( -
-
-
- {">"}_ -
- Transaction History +
+ + +
+ + Base wallet +
- + {activeIdx !== null && ( + + )}
-
-
Terminal
-
- {lines.map(renderLine)} - {running &&
{"▋"}
} -
+ +
+ {!ex && ( +
+
+ Ask your assistant about your transaction history once mcp.base.org is connected: +
+
+ {examples.map((e, i) => pick(i)}>{e.prompt})} +
+
+ )} + {ex && <>{ex.prompt}{renderEvents()}}
-
- {!running && !done && } - {done && } + +
+
+ + Write a message... + Sonnet 4.6 + +
+
+ Demo · Read-only — no approval required for transaction history +
); diff --git a/docs/snippets/AuthApprovalDemo.jsx b/docs/snippets/AuthApprovalDemo.jsx new file mode 100644 index 000000000..afa5cee53 --- /dev/null +++ b/docs/snippets/AuthApprovalDemo.jsx @@ -0,0 +1,204 @@ + +// Auth approval demo — mock of the keys.coinbase.com Allow modal shown +// on first wallet-tool use. The client name is hardcoded because Mintlify +// does not expose the active selection to JSX snippets. (Cross-tab +// sync would require wrapping this in another visible Tabs block.) +export const AuthApprovalDemo = ({ client = "Claude" }) => { + const sans = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"; + + const c = { + bg: "#0a0a0a", + cardBorder: "#1c1c1c", + rowBorder: "#1f1f1f", + text: "#ffffff", + muted: "#9a9a9a", + dim: "#6b6b6b", + accent: "#a796f7", + accentRing: "#c8bcff", + btnDark: "#1c1c1c", + iconBlue: "#2a64ff", + iconBlue2: "#5b8eff", + permIconBg: "#1c1c1c", + permIconFg: "#d2d2d2", + }; + + const permissions = [ + { label: "View address, balances & activity." }, + { label: "Request approval for sends and swaps." }, + { label: "Sign messages and typed data on request." }, + { label: "Read onchain data on Base." }, + ]; + + const EyeIcon = () => ( + + + + + ); + const SendIcon = () => ( + + + + ); + const SignIcon = () => ( + + + + ); + const ChainIcon = () => ( + + + + + ); + const icons = [, , , ]; + + return ( +
+ + +
+ {/* Signed-in row */} +
+ + + Signed in as 0x71Dc…7244 + +
+ + {/* Body */} +
+ {/* Icons */} +
+
+ + + + + +
+
+ + + + +
+
+ +

+ Allow {client} to access your account. +

+ +

+ By continuing, you allow {client} to: +

+ +
+ {permissions.map((p, i) => ( +
+
+ {icons[i]} +
+ + {p.label} + +
+ ))} +
+
+ +
+ + + + + + + + +
+
+ +
+ Preview · Shown at keys.coinbase.com on first wallet-tool use +
+
+ ); +}; diff --git a/docs/snippets/DataFetchingDemo.jsx b/docs/snippets/DataFetchingDemo.jsx index 3853403fd..354322925 100644 --- a/docs/snippets/DataFetchingDemo.jsx +++ b/docs/snippets/DataFetchingDemo.jsx @@ -1,123 +1,254 @@ -import { useState, useEffect, useRef } from "react"; export const DataFetchingDemo = () => { - const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8" }; - - const flows = { - wallets: [ - { delay: 450, - left: [{ t: "> Show me my wallets", c: "active" }, { t: " ← get_wallets()", c: "muted" }], - right: [{ t: "── get_wallets ─────────────────────", c: "dim" }, { t: " (no params required)", c: "muted" }] }, - { delay: 700, - left: [{ t: " Base Account: 0x4a3f...b7c1 ✓", c: "success" }, { t: " Agent Wallet: 0x9c2d...e4f8 (not in session)", c: "muted" }], - right: [{ t: "", c: "dim" }, { t: ' { type: "base-account",', c: "code" }, { t: ' address: "0x4a3f...b7c1",', c: "code" }, { t: ' inSession: true }', c: "code" }] }, - { delay: 500, - left: [{ t: "", c: "dim" }, { t: " 2 wallets found", c: "success" }], - right: [{ t: "", c: "dim" }, { t: ' { type: "agent-wallet",', c: "code" }, { t: ' address: "0x9c2d...e4f8",', c: "code" }, { t: ' inSession: false }', c: "code" }] }, - ], - portfolio: [ - { delay: 450, - left: [{ t: "> What's my balance on Base?", c: "active" }, { t: " ← get_portfolio(chain=base)", c: "muted" }], - right: [{ t: "── get_portfolio ────────────────────", c: "dim" }, { t: " chain: base", c: "muted" }] }, - { delay: 700, - left: [{ t: " USDC 245.80 $245.80", c: "success" }, { t: " ETH 0.0412 $148.33", c: "success" }], - right: [{ t: "", c: "dim" }, { t: " totalValue: $430.15", c: "success" }, { t: " assetCount: 3", c: "code" }] }, - { delay: 500, - left: [{ t: " WETH 0.0100 $36.02", c: "success" }, { t: " Total: $430.15 on Base ✓", c: "success" }], - right: [{ t: "", c: "dim" }, { t: ' { symbol: "WETH",', c: "code" }, { t: ' balance: "0.0100",', c: "code" }, { t: ' usdValue: "$36.02" }', c: "code" }] }, - ], - history: [ - { delay: 450, - left: [{ t: "> Show my recent USDC sends", c: "active" }, { t: " ← get_transaction_history(asset=USDC, limit=4)", c: "muted" }], - right: [{ t: "── get_transaction_history ─────────", c: "dim" }, { t: " asset: USDC limit: 4", c: "muted" }] }, - { delay: 700, - left: [{ t: " send -10.00 USDC alice.base.eth", c: "code" }, { t: " recv +50.00 USDC coinbase.com ", c: "success" }], - right: [{ t: "", c: "dim" }, { t: " hasMore: true", c: "muted" }, { t: ' nextCursor: "cur_abc..."', c: "muted" }] }, - { delay: 500, - left: [{ t: " send -5.00 USDC bob.eth ", c: "code" }, { t: " recv +100.00 USDC 0x9f3a...2e01 ", c: "success" }], - right: [{ t: "", c: "dim" }, { t: " 4 USDC transactions returned", c: "success" }, { t: " More pages available", c: "muted" }] }, - ], + const sans = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"; + const serif = "'Tiempos Headline','Iowan Old Style','Source Serif Pro',ui-serif,Georgia,serif"; + const mono = "ui-monospace,'SF Mono','Cascadia Code',Menlo,Monaco,Consolas,monospace"; + + const c = { + bg: "#1f1e1d", header: "#262624", border: "#34322f", inputBg: "#2a2926", + text: "#f5f4ed", body: "#e8e4dc", muted: "#a8a39d", dim: "#6b6663", + accent: "#D97757", bubble: "#2c2b28", bubbleText: "#f5f4ed", + code: "#e89972", codeBg: "rgba(217,119,87,0.12)", + toolBg: "#272622", toolBorder: "#3a3835", success: "#a3c585", }; - const [choice, setChoice] = useState(null); - const [leftLines, setLeft] = useState([{ t: "> Try a read tool:", c: "muted" }]); - const [rightLines, setRight]= useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const leftRef = useRef(null); - const rightRef = useRef(null); - - useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); - useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); - useEffect(() => { if (rightRef.current) rightRef.current.scrollTop = rightRef.current.scrollHeight; }, [rightLines]); - - const reset = () => { setChoice(null); setLeft([{ t: "> Try a read tool:", c: "muted" }]); setRight([]); setRunning(false); setDone(false); }; - - const pick = (key) => { - if (choice) return; - const labels = { wallets: "get_wallets", portfolio: "get_portfolio", history: "get_transaction_history" }; - setChoice(key); - setLeft(p => [...p, { t: " [" + labels[key] + "]", c: "active" }]); - const steps = flows[key]; - setRunning(true); - let i = 0; - const next = () => { - if (i >= steps.length) { setRunning(false); setDone(true); return; } - const s = steps[i]; - setTimeout(() => { - if (s.left) setLeft(p => [...p, ...s.left]); - if (s.right) setRight(p => [...p, ...s.right]); - i++; next(); - }, s.delay); - }; - setTimeout(next, 200); + const examples = [ + { + prompt: "What's my balance on Base?", + events: [ + { delay: 380, type: "thinking" }, + { delay: 550, type: "tool", tool: { server: "base-account", action: "get_portfolio", args: { chain: "base" } } }, + { delay: 600, type: "text", text: "Your current portfolio on Base:" }, + { delay: 250, type: "rows", rows: [ + { token: "USDC", amount: "245.80", value: "$245.80" }, + { token: "ETH", amount: "0.0412", value: "$148.33" }, + { token: "WETH", amount: "0.0100", value: "$36.02" }, + ]}, + { delay: 400, type: "confirm", text: "Total: $430.15 on Base" }, + ], + }, + { + prompt: "Check the balance of jesse.base.eth", + events: [ + { delay: 380, type: "thinking" }, + { delay: 550, type: "tool", tool: { server: "base-account", action: "get_portfolio", args: { address: "jesse.base.eth", chain: "base" } } }, + { delay: 600, type: "text", text: "Balances for jesse.base.eth (0xd8dA…6045) on Base:" }, + { delay: 250, type: "rows", rows: [ + { token: "ETH", amount: "1,842.14", value: "$6.63M" }, + { token: "USDC", amount: "28,450.00", value: "$28.4K" }, + { token: "DAI", amount: "10,000.00", value: "$10.0K" }, + ]}, + ], + }, + { + prompt: "What's my total balance across all chains?", + events: [ + { delay: 380, type: "thinking" }, + { delay: 550, type: "tool", tool: { server: "base-account", action: "get_portfolio", args: { chain: "base" } } }, + { delay: 600, type: "tool", tool: { server: "base-account", action: "get_portfolio", args: { chain: "ethereum" } } }, + { delay: 500, type: "text", text: "Your balances across networks:" }, + { delay: 250, type: "rows", rows: [ + { token: "Base", amount: "$430.15", value: "USDC · ETH · WETH" }, + { token: "Ethereum", amount: "$284.20", value: "ETH · USDC" }, + ]}, + { delay: 400, type: "confirm", text: "Total: $714.35 across all chains" }, + ], + }, + ]; + + const [activeIdx, setActiveIdx] = useState(null); + const [eventIdx, setEventIdx] = useState(0); + const scrollRef = useRef(null); + const timersRef = useRef([]); + + const clearTimers = () => { timersRef.current.forEach(clearTimeout); timersRef.current = []; }; + + useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [eventIdx, activeIdx]); + useEffect(() => () => clearTimers(), []); + + const pick = (idx) => { + if (activeIdx !== null) return; + setActiveIdx(idx); + setEventIdx(0); + clearTimers(); + let cumulative = 0; + examples[idx].events.forEach((e, i) => { + cumulative += e.delay; + timersRef.current.push(setTimeout(() => setEventIdx(i + 1), cumulative)); + }); + }; + + const reset = () => { clearTimers(); setActiveIdx(null); setEventIdx(0); }; + const ex = activeIdx !== null ? examples[activeIdx] : null; + + const TrafficLights = () => ( +
+ + + +
+ ); + + const UserBubble = ({ children }) => ( +
+
{children}
+
+ ); + + const ToolCall = ({ tool, completed }) => ( +
+
+ + {completed + ? + : } + + + {tool.server} + · + {tool.action} + ( + {Object.entries(tool.args).map(([k, v], i, arr) => ( + {k}: "{v}"{i < arr.length - 1 && , } + ))} + ) + +
+
+ ); + + const Thinking = () => ( +
+ + {[0, 1, 2].map(i => )} + + Thinking +
+ ); + + const ResponseText = ({ children, top }) => ( +
{children}
+ ); + + const ResponseRows = ({ rows }) => ( +
+ {rows.map((r, i) => ( +
+ + {r.token} + {r.amount} + {r.value} +
+ ))} +
+ ); + + const Confirm = ({ text }) => ( +
+ + {text} +
+ ); + + const ChipBtn = ({ onClick, children }) => { + const [hover, setHover] = useState(false); + return ( + + ); }; - const renderLine = (item, i) => { - if (!item.t) return
; - return
{item.t}
; + const renderEvents = () => { + if (!ex) return null; + const shown = ex.events.slice(0, eventIdx); + return shown.map((event, i) => { + if (event.type === "thinking") { + if (i < shown.length - 1) return null; + return ; + } + if (event.type === "tool") { + const hasLater = shown.slice(i + 1).some(e => e.type !== "thinking"); + return ; + } + if (event.type === "text") return {event.text}; + if (event.type === "rows") return ; + if (event.type === "confirm") return ; + return null; + }); }; - const btnBase = { fontFamily: mono, fontSize: 12, color: "#60a5fa", background: "transparent", border: "1px solid #27272a", borderRadius: 4, cursor: "pointer", padding: "2px 8px", marginRight: 6, lineHeight: "20px" }; - const onEnter = (e) => { e.currentTarget.style.color = "#e4e4e7"; e.currentTarget.style.background = "#1c1c1e"; e.currentTarget.style.borderColor = "#3f3f46"; }; - const onLeave = (e) => { e.currentTarget.style.color = "#60a5fa"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "#27272a"; }; return ( -
-
-
- {">"}_ -
- Read Tools +
+ + +
+ + Base wallet +
- + {activeIdx !== null && ( + + )}
-
-
-
Agent
-
- {leftLines.map(renderLine)} - {!choice && ( -
- - - -
- )} - {running &&
{"▋"}
} + +
+ {!ex && ( +
+
+ Check any wallet's balance once mcp.base.org is connected: +
+
+ {examples.map((e, i) => pick(i)}>{e.prompt})} +
+ )} + {ex && <>{ex.prompt}{renderEvents()}} +
+ +
+
+ + Write a message... + Sonnet 4.6 +
-
-
MCP Response
-
{rightLines.map(renderLine)}
+
+ Demo · Read-only — no approval required to check balances
-
- {done && } -
); }; diff --git a/docs/snippets/PaymentsQuickstartDemo.jsx b/docs/snippets/PaymentsQuickstartDemo.jsx index 05a33e902..1db7faa9a 100644 --- a/docs/snippets/PaymentsQuickstartDemo.jsx +++ b/docs/snippets/PaymentsQuickstartDemo.jsx @@ -1,143 +1,247 @@ -import { useState, useEffect, useRef } from "react"; -// CDP x402 payments demo — used in payments.mdx +// CDP x402 payments demo — used in payments.mdx and guides/pay-for-services.mdx export const PaymentsQuickstartDemo = () => { - const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", + const sans = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"; + const serif = "'Tiempos Headline','Iowan Old Style','Source Serif Pro',ui-serif,Georgia,serif"; + const mono = "ui-monospace,'SF Mono','Cascadia Code',Menlo,Monaco,Consolas,monospace"; + + const c = { + bg: "#1f1e1d", header: "#262624", border: "#34322f", inputBg: "#2a2926", + text: "#f5f4ed", body: "#e8e4dc", muted: "#a8a39d", dim: "#6b6663", + accent: "#D97757", bubble: "#2c2b28", bubbleText: "#f5f4ed", + code: "#e89972", codeBg: "rgba(217,119,87,0.12)", + toolBg: "#272622", toolBorder: "#3a3835", success: "#a3c585", }; - const steps = [ - { delay: 350, left: [{ t: "> npx skills add coinbase/agentic-wallet-skills", c: "active" }], right: [ - { t: "── Installing CDP skills ───────────────", c: "dim" }, - { t: "authenticate-wallet", c: "muted" }, - { t: "pay-for-service", c: "muted" }, - { t: "search-for-service", c: "muted" }, - { t: "monetize-service", c: "muted" }, - ]}, - { delay: 700, left: [{ t: " ✓ CDP Agentic Wallet skills installed", c: "success" }], right: [] }, - { delay: 500, left: [{ t: "> Sign in with you@email.com", c: "active" }], right: [] }, - { delay: 650, left: [{ t: " ✓ CDP wallet authenticated 0x4a3f...b7c1", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── wallet ready ────────────────────────", c: "dim" }, - { t: " address: 0x4a3f...b7c1", c: "success" }, - { t: " balance: 10.00 USDC", c: "success" }, - ]}, - { delay: 500, left: [{ t: "> Find a weather API and get the NYC forecast", c: "active" }], right: [ - { t: "", c: "dim" }, - { t: "── search-for-service ──────────────────", c: "dim" }, - { t: 'query: "weather forecast"', c: "code" }, - ]}, - { delay: 700, left: [{ t: " ← found: weather.x402.io · 0.001 USDC/req", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "── pay-for-service ─────────────────────", c: "dim" }, - { t: "GET /v1/forecast?city=NYC", c: "code" }, - { t: "← HTTP 402 Payment Required", c: "muted" }, - ]}, - { delay: 550, left: [{ t: " paying 0.001 USDC...", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: " Paying 0.001 USDC · signing...", c: "muted" }, - { t: " Retrying with X-Payment-Sig", c: "muted" }, - ]}, - { delay: 600, left: [{ t: " ← 200 OK · forecast received", c: "success", bold: true }], right: [ - { t: "", c: "dim" }, - { t: "HTTP/1.1 200 OK", c: "success" }, - { t: '{"city":"NYC","temp":"68°F",...}', c: "code" }, - ]}, + const examples = [ + { + prompt: "Find a weather API that accepts x402 and get the NYC forecast", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "agentic-wallet", action: "search_for_service", args: { query: "weather forecast" } } }, + { delay: 600, type: "text", text: "Found weather.x402.io — 0.001 USDC per request. Paying and fetching..." }, + { delay: 450, type: "tool", tool: { server: "agentic-wallet", action: "pay_for_service", args: { url: "weather.x402.io/forecast?city=NYC", amount: "0.001 USDC" } } }, + { delay: 1000, type: "confirm", text: "NYC: 68°F, partly cloudy · paid 0.001 USDC" }, + ], + }, + { + prompt: "Pay for a stock price API call for AAPL", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "agentic-wallet", action: "search_for_service", args: { query: "stock price API" } } }, + { delay: 600, type: "text", text: "Found stocks.x402.io — 0.002 USDC per request. Fetching AAPL..." }, + { delay: 450, type: "tool", tool: { server: "agentic-wallet", action: "pay_for_service", args: { url: "stocks.x402.io/price?symbol=AAPL", amount: "0.002 USDC" } } }, + { delay: 1000, type: "confirm", text: "AAPL: $189.42 · paid 0.002 USDC" }, + ], + }, + { + prompt: "Monetize my news API with x402 payments", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "agentic-wallet", action: "monetize_service", args: { endpoint: "/api/news", price: "0.005 USDC" } } }, + { delay: 600, type: "text", text: "Your endpoint is now x402-protected. Any agent can pay per-request:" }, + { delay: 300, type: "rows", rows: [ + { token: "Endpoint", amount: "/api/news", value: "HTTP 402 on unauthorized" }, + { token: "Price", amount: "0.005 USDC/req", value: "paid in USDC on Base" }, + { token: "Facilitator", amount: "x402.org", value: "handles verification" }, + ]}, + { delay: 500, type: "confirm", text: "Service live · any x402 agent can now pay to access" }, + ], + }, ]; - const [leftLines, setLeftLines] = useState([]); - const [rightLines, setRightLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const leftRef = useRef(null); - const rightRef = useRef(null); - - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); - - useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); - useEffect(() => { if (rightRef.current) rightRef.current.scrollTop = rightRef.current.scrollHeight; }, [rightLines]); - - const play = () => { - setLeftLines([]); - setRightLines([]); - setRunning(true); - setDone(false); - let i = 0; - const next = () => { - if (i >= steps.length) { setRunning(false); setDone(true); return; } - const s = steps[i]; - setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); - }, s.delay); - }; - next(); + const [activeIdx, setActiveIdx] = useState(null); + const [eventIdx, setEventIdx] = useState(0); + const scrollRef = useRef(null); + const timersRef = useRef([]); + + const clearTimers = () => { timersRef.current.forEach(clearTimeout); timersRef.current = []; }; + + useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [eventIdx, activeIdx]); + useEffect(() => () => clearTimers(), []); + + const pick = (idx) => { + if (activeIdx !== null) return; + setActiveIdx(idx); + setEventIdx(0); + clearTimers(); + let cumulative = 0; + examples[idx].events.forEach((e, i) => { + cumulative += e.delay; + timersRef.current.push(setTimeout(() => setEventIdx(i + 1), cumulative)); + }); }; - useEffect(() => { setTimeout(play, 350); }, []); // eslint-disable-line react-hooks/exhaustive-deps + const reset = () => { clearTimers(); setActiveIdx(null); setEventIdx(0); }; + const ex = activeIdx !== null ? examples[activeIdx] : null; - const renderLine = (item, i) => { - if (!item.t) return
; + const TrafficLights = () => ( +
+ + + +
+ ); + + const UserBubble = ({ children }) => ( +
+
{children}
+
+ ); + + const ToolCall = ({ tool, completed }) => ( +
+
+ + {completed + ? + : } + + + {tool.server} + · + {tool.action} + ( + {Object.entries(tool.args).map(([k, v], i, arr) => ( + {k}: "{v}"{i < arr.length - 1 && , } + ))} + ) + +
+
+ ); + + const Thinking = () => ( +
+ + {[0, 1, 2].map(i => )} + + Thinking +
+ ); + + const ResponseText = ({ children, top }) => ( +
{children}
+ ); + + const ResponseRows = ({ rows }) => ( +
+ {rows.map((r, i) => ( +
+ + {r.token} + {r.amount} + {r.value} +
+ ))} +
+ ); + + const Confirm = ({ text }) => ( +
+ + {text} +
+ ); + + const ChipBtn = ({ onClick, children }) => { + const [hover, setHover] = useState(false); return ( -
{item.t}
+ ); }; + const renderEvents = () => { + if (!ex) return null; + const shown = ex.events.slice(0, eventIdx); + return shown.map((event, i) => { + if (event.type === "thinking") { + if (i < shown.length - 1) return null; + return ; + } + if (event.type === "tool") { + const hasLater = shown.slice(i + 1).some(e => e.type !== "thinking"); + return ; + } + if (event.type === "text") return {event.text}; + if (event.type === "rows") return ; + if (event.type === "confirm") return ; + return null; + }); + }; + return ( -
-
-
- {">"}_ -
- x402 via CDP Agentic Wallet +
+ + +
+ + CDP Agentic Wallet · x402 +
- + {activeIdx !== null && ( + + )}
-
-
-
- Agent -
-
- {leftLines.map(renderLine)} - {running &&
{"▋"}
} -
-
-
-
- HTTP Trace -
-
- {rightLines.map(renderLine)} +
+ {!ex && ( +
+
+ Try x402 agent payments with the CDP Agentic Wallet: +
+
+ {examples.map((e, i) => pick(i)}>{e.prompt})} +
-
+ )} + {ex && <>{ex.prompt}{renderEvents()}}
-
- {done && ( - - )} + Write a message... + Sonnet 4.6 + +
+
+ Demo · x402 payments settle instantly on Base · no approval required +
); diff --git a/docs/snippets/TradeExecutionDemo.jsx b/docs/snippets/TradeExecutionDemo.jsx index 6fbc00fe8..5ed44dd99 100644 --- a/docs/snippets/TradeExecutionDemo.jsx +++ b/docs/snippets/TradeExecutionDemo.jsx @@ -1,79 +1,237 @@ -import { useState, useEffect, useRef } from "react"; export const TradeExecutionDemo = () => { - const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8", warn: "#fb923c" }; - - const steps = [ - { delay: 400, lines: [{ t: "> Send 50 DEGEN to alice.base.eth", c: "active" }] }, - { delay: 500, lines: [ - { t: " ── search_tokens ──────────────────────────", c: "dim" }, - { t: ' query: "DEGEN" chain: base', c: "muted" }, - ]}, - { delay: 650, lines: [ - { t: ' ← name: "Degen" symbol: "DEGEN"', c: "code" }, - { t: ' address: "0x4ed4...9fa2" decimals: 18', c: "code" }, - ]}, - { delay: 500, lines: [{ t: "", c: "dim" }, { t: "> send(alice.base.eth, 50 DEGEN, 0x4ed4..., 18)", c: "active" }] }, - { delay: 500, lines: [ - { t: " ── approval required ──────────────────────", c: "warn" }, - { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, - ]}, - { delay: 500, lines: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }] }, - { delay: 1000, lines: [ - { t: ' ← status: "confirmed"', c: "success" }, - { t: " ✓ 50 DEGEN sent to alice.base.eth", c: "success" }, - ]}, + const sans = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"; + const serif = "'Tiempos Headline','Iowan Old Style','Source Serif Pro',ui-serif,Georgia,serif"; + const mono = "ui-monospace,'SF Mono','Cascadia Code',Menlo,Monaco,Consolas,monospace"; + + const c = { + bg: "#1f1e1d", header: "#262624", border: "#34322f", inputBg: "#2a2926", + text: "#f5f4ed", body: "#e8e4dc", muted: "#a8a39d", dim: "#6b6663", + accent: "#D97757", bubble: "#2c2b28", bubbleText: "#f5f4ed", + code: "#e89972", codeBg: "rgba(217,119,87,0.12)", + toolBg: "#272622", toolBorder: "#3a3835", success: "#a3c585", + }; + + const examples = [ + { + prompt: "Send 10 USDC to alice.base.eth", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "base-account", action: "send", args: { to: "alice.base.eth", asset: "USDC", amount: "10", chain: "base" } } }, + { delay: 500, type: "text", text: "Resolved alice.base.eth → 0x71C7…976F. Approve to send:" }, + { delay: 250, type: "approval", url: "keys.coinbase.com/approve/req_abc123" }, + { delay: 1100, type: "confirm", text: "Sent 10 USDC to alice.base.eth" }, + ], + }, + { + prompt: "Send 50 DEGEN to bob.base.eth", + events: [ + { delay: 380, type: "thinking" }, + { delay: 550, type: "tool", tool: { server: "base-account", action: "search_tokens", args: { query: "DEGEN", chain: "base" } } }, + { delay: 500, type: "text", text: "Found DEGEN at 0x4ed4…9fa2. Sending to bob.base.eth..." }, + { delay: 400, type: "tool", tool: { server: "base-account", action: "send", args: { to: "bob.base.eth", asset: "0x4ed4…9fa2", amount: "50", chain: "base" } } }, + { delay: 250, type: "approval", url: "keys.coinbase.com/approve/req_degen01" }, + { delay: 1100, type: "confirm", text: "Sent 50 DEGEN to bob.base.eth" }, + ], + }, + { + prompt: "Send 0.01 ETH to jesse.base.eth", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "base-account", action: "send", args: { to: "jesse.base.eth", asset: "ETH", amount: "0.01", chain: "base" } } }, + { delay: 500, type: "text", text: "Resolved jesse.base.eth → 0xd8dA…6045. Approve to send:" }, + { delay: 250, type: "approval", url: "keys.coinbase.com/approve/req_eth01" }, + { delay: 1100, type: "confirm", text: "Sent 0.01 ETH to jesse.base.eth" }, + ], + }, ]; - const [lines, setLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const ref = useRef(null); - - useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); - useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]); - - const reset = () => { setLines([]); setRunning(false); setDone(false); }; - const run = () => { - if (running || done) return; - setRunning(true); - let i = 0; - const next = () => { - if (i >= steps.length) { setRunning(false); setDone(true); return; } - setTimeout(() => { setLines(p => [...p, ...steps[i].lines]); i++; next(); }, steps[i].delay); - }; - next(); + const [activeIdx, setActiveIdx] = useState(null); + const [eventIdx, setEventIdx] = useState(0); + const scrollRef = useRef(null); + const timersRef = useRef([]); + + const clearTimers = () => { timersRef.current.forEach(clearTimeout); timersRef.current = []; }; + + useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [eventIdx, activeIdx]); + useEffect(() => () => clearTimers(), []); + + const pick = (idx) => { + if (activeIdx !== null) return; + setActiveIdx(idx); + setEventIdx(0); + clearTimers(); + let cumulative = 0; + examples[idx].events.forEach((e, i) => { + cumulative += e.delay; + timersRef.current.push(setTimeout(() => setEventIdx(i + 1), cumulative)); + }); }; - const renderLine = (item, i) => { - if (!item.t) return
; - return
{item.t}
; + const reset = () => { clearTimers(); setActiveIdx(null); setEventIdx(0); }; + const ex = activeIdx !== null ? examples[activeIdx] : null; + + const TrafficLights = () => ( +
+ + + +
+ ); + + const UserBubble = ({ children }) => ( +
+
{children}
+
+ ); + + const ToolCall = ({ tool, completed }) => ( +
+
+ + {completed + ? + : } + + + {tool.server} + · + {tool.action} + ( + {Object.entries(tool.args).map(([k, v], i, arr) => ( + {k}: "{v}"{i < arr.length - 1 && , } + ))} + ) + +
+
+ ); + + const Thinking = () => ( +
+ + {[0, 1, 2].map(i => )} + + Thinking +
+ ); + + const ResponseText = ({ children, top }) => ( +
{children}
+ ); + + const ApprovalLink = ({ url }) => ( +
+ + + {url} + +
+ ); + + const Confirm = ({ text }) => ( +
+ + {text} +
+ ); + + const ChipBtn = ({ onClick, children }) => { + const [hover, setHover] = useState(false); + return ( + + ); + }; + + const renderEvents = () => { + if (!ex) return null; + const shown = ex.events.slice(0, eventIdx); + return shown.map((event, i) => { + if (event.type === "thinking") { + if (i < shown.length - 1) return null; + return ; + } + if (event.type === "tool") { + const hasLater = shown.slice(i + 1).some(e => e.type !== "thinking"); + return ; + } + if (event.type === "text") return {event.text}; + if (event.type === "approval") return ; + if (event.type === "confirm") return ; + return null; + }); }; return ( -
-
-
- {">"}_ -
- Token Search + Send +
+ + +
+ + Base wallet +
- + {activeIdx !== null && ( + + )}
-
-
Terminal
-
- {lines.map(renderLine)} - {running &&
{"▋"}
} -
+ +
+ {!ex && ( +
+
+ Send tokens to any address or name once mcp.base.org is connected: +
+
+ {examples.map((e, i) => pick(i)}>{e.prompt})} +
+
+ )} + {ex && <>{ex.prompt}{renderEvents()}}
-
- {!running && !done && } - {done && } + +
+
+ + Write a message... + Sonnet 4.6 + +
+
+ Demo · Every send requires your approval at keys.coinbase.com +
); diff --git a/docs/snippets/TradingQuickstartDemo.jsx b/docs/snippets/TradingQuickstartDemo.jsx index 3e8cd48e1..8b4122e70 100644 --- a/docs/snippets/TradingQuickstartDemo.jsx +++ b/docs/snippets/TradingQuickstartDemo.jsx @@ -1,87 +1,262 @@ -import { useState, useEffect, useRef } from "react"; export const TradingQuickstartDemo = () => { - const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8", warn: "#fb923c" }; - - const steps = [ - { delay: 400, lines: [{ t: "> Swap 100 USDC for ETH on Base", c: "active" }] }, - { delay: 500, lines: [ - { t: " ── swap() ─────────────────────────────", c: "dim" }, - { t: " fromAsset: USDC toAsset: ETH amount: 100", c: "muted" }, - ]}, - { delay: 700, lines: [ - { t: " ← quote ready", c: "muted" }, - { t: " 0.03512 ETH · price impact 0.09%", c: "code" }, - ]}, - { delay: 500, lines: [{ t: "", c: "dim" }, { t: " ── approval required ──────────────────────", c: "warn" }] }, - { delay: 400, lines: [ - { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, - { t: ' requestId: "req_swap01"', c: "muted" }, - ]}, - { delay: 500, lines: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }] }, - { delay: 1000, lines: [{ t: " ← user approved ✓", c: "success" }] }, - { delay: 500, lines: [ - { t: " ── get_request_status ─────────────────────", c: "dim" }, - { t: ' status: "confirmed" received: "0.03512 ETH"', c: "success" }, - ]}, - { delay: 400, lines: [{ t: "", c: "dim" }, { t: " ✓ 0.03512 ETH received", c: "success" }] }, + const sans = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"; + const serif = "'Tiempos Headline','Iowan Old Style','Source Serif Pro',ui-serif,Georgia,serif"; + const mono = "ui-monospace,'SF Mono','Cascadia Code',Menlo,Monaco,Consolas,monospace"; + + const c = { + bg: "#1f1e1d", header: "#262624", border: "#34322f", inputBg: "#2a2926", + text: "#f5f4ed", body: "#e8e4dc", muted: "#a8a39d", dim: "#6b6663", + accent: "#D97757", bubble: "#2c2b28", bubbleText: "#f5f4ed", + code: "#e89972", codeBg: "rgba(217,119,87,0.12)", + toolBg: "#272622", toolBorder: "#3a3835", success: "#a3c585", + }; + + const examples = [ + { + prompt: "Swap 100 USDC for ETH on Base", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "base-account", action: "swap", args: { fromAsset: "USDC", toAsset: "ETH", amount: "100", chain: "base" } } }, + { delay: 500, type: "text", text: "Quote ready: 0.03512 ETH · price impact 0.09%. Approve to swap:" }, + { delay: 250, type: "approval", url: "keys.coinbase.com/approve/req_swap01" }, + { delay: 1100, type: "confirm", text: "Swapped 100 USDC → 0.03512 ETH" }, + ], + }, + { + prompt: "Swap 0.05 ETH to USDC — best rate", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "aerodrome", action: "get_quote", args: { from: "0.05 ETH", to: "USDC" } } }, + { delay: 700, type: "tool", tool: { server: "uniswap-v3", action: "get_quote", args: { from: "0.05 ETH", to: "USDC" } } }, + { delay: 600, type: "text", text: "Routed across two Base DEXes — Uniswap v3 has the better fill:" }, + { delay: 250, type: "rows", rows: [ + { token: "Aerodrome", amount: "178.92 USDC", value: "0.30% fee · slippage 0.18%" }, + { token: "Uniswap v3 (best)", amount: "179.41 USDC", value: "0.05% fee · slippage 0.12%" }, + ]}, + { delay: 700, type: "tool", tool: { server: "base-account", action: "swap", args: { route: "ETH→USDC", min_out: "179.20 USDC" } } }, + { delay: 450, type: "approval", url: "keys.coinbase.com/approve/req_swap02" }, + { delay: 1100, type: "confirm", text: "Swapped 0.05 ETH → 179.41 USDC on Uniswap v3" }, + ], + }, + { + prompt: "Convert 200 USDC to cbBTC", + events: [ + { delay: 380, type: "thinking" }, + { delay: 550, type: "tool", tool: { server: "base-account", action: "search_tokens", args: { query: "cbBTC", chain: "base" } } }, + { delay: 500, type: "tool", tool: { server: "base-account", action: "swap", args: { fromAsset: "USDC", toAsset: "cbBTC", amount: "200", chain: "base" } } }, + { delay: 500, type: "text", text: "Quote ready: 0.00210 cbBTC at current rates. Approve to swap:" }, + { delay: 250, type: "approval", url: "keys.coinbase.com/approve/req_swap03" }, + { delay: 1100, type: "confirm", text: "Swapped 200 USDC → 0.00210 cbBTC" }, + ], + }, ]; - const [lines, setLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const ref = useRef(null); - - useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); - useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]); - - const reset = () => { setLines([]); setRunning(false); setDone(false); }; - const run = () => { - if (running || done) return; - setRunning(true); - let i = 0; - const next = () => { - if (i >= steps.length) { setRunning(false); setDone(true); return; } - const s = steps[i]; - setTimeout(() => { setLines(p => [...p, ...s.lines]); i++; next(); }, s.delay); - }; - next(); + const [activeIdx, setActiveIdx] = useState(null); + const [eventIdx, setEventIdx] = useState(0); + const scrollRef = useRef(null); + const timersRef = useRef([]); + + const clearTimers = () => { timersRef.current.forEach(clearTimeout); timersRef.current = []; }; + + useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [eventIdx, activeIdx]); + useEffect(() => () => clearTimers(), []); + + const pick = (idx) => { + if (activeIdx !== null) return; + setActiveIdx(idx); + setEventIdx(0); + clearTimers(); + let cumulative = 0; + examples[idx].events.forEach((e, i) => { + cumulative += e.delay; + timersRef.current.push(setTimeout(() => setEventIdx(i + 1), cumulative)); + }); + }; + + const reset = () => { clearTimers(); setActiveIdx(null); setEventIdx(0); }; + const ex = activeIdx !== null ? examples[activeIdx] : null; + + const TrafficLights = () => ( +
+ + + +
+ ); + + const UserBubble = ({ children }) => ( +
+
{children}
+
+ ); + + const ToolCall = ({ tool, completed }) => ( +
+
+ + {completed + ? + : } + + + {tool.server} + · + {tool.action} + ( + {Object.entries(tool.args).map(([k, v], i, arr) => ( + {k}: "{v}"{i < arr.length - 1 && , } + ))} + ) + +
+
+ ); + + const Thinking = () => ( +
+ + {[0, 1, 2].map(i => )} + + Thinking +
+ ); + + const ResponseText = ({ children, top }) => ( +
{children}
+ ); + + const ResponseRows = ({ rows }) => ( +
+ {rows.map((r, i) => ( +
+ + {r.token} + {r.amount} + {r.value} +
+ ))} +
+ ); + + const ApprovalLink = ({ url }) => ( +
+ + + {url} + +
+ ); + + const Confirm = ({ text }) => ( +
+ + {text} +
+ ); + + const ChipBtn = ({ onClick, children }) => { + const [hover, setHover] = useState(false); + return ( + + ); }; - const renderLine = (item, i) => { - if (!item.t) return
; - return
{item.t}
; + const renderEvents = () => { + if (!ex) return null; + const shown = ex.events.slice(0, eventIdx); + return shown.map((event, i) => { + if (event.type === "thinking") { + if (i < shown.length - 1) return null; + return ; + } + if (event.type === "tool") { + const hasLater = shown.slice(i + 1).some(e => e.type !== "thinking"); + return ; + } + if (event.type === "text") return {event.text}; + if (event.type === "rows") return ; + if (event.type === "approval") return ; + if (event.type === "confirm") return ; + return null; + }); }; return ( -
-
-
- {">"}_ -
- Swap Tokens +
+ + +
+ + Base wallet +
- + {activeIdx !== null && ( + + )} +
+ +
+ {!ex && ( +
+
+ Swap any token on Base once mcp.base.org is connected: +
+
+ {examples.map((e, i) => pick(i)}>{e.prompt})} +
+
+ )} + {ex && <>{ex.prompt}{renderEvents()}}
-
-
- Terminal + +
+
+ + Write a message... + Sonnet 4.6 +
-
- {lines.map(renderLine)} - {running &&
{"▋"}
} +
+ Demo · Every swap requires your approval at keys.coinbase.com
-
- {!running && !done && } - {done && } -
); }; diff --git a/docs/snippets/WalletSetupDemo.jsx b/docs/snippets/WalletSetupDemo.jsx index 946101314..11c6ecbbb 100644 --- a/docs/snippets/WalletSetupDemo.jsx +++ b/docs/snippets/WalletSetupDemo.jsx @@ -1,4 +1,3 @@ -import { useState, useEffect, useRef } from "react"; export const WalletSetupDemo = () => { const sans = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"; @@ -29,13 +28,13 @@ export const WalletSetupDemo = () => { // (thinking auto-hides once the next event renders) const examples = [ { - prompt: "Send 5 USDC to vitalik.base.eth", + prompt: "Send 5 USDC to jesse.base.eth", events: [ { delay: 380, type: "thinking" }, - { delay: 600, type: "tool", tool: { server: "base-account", action: "send", args: { to: "vitalik.base.eth", asset: "USDC", amount: "5" } } }, - { delay: 550, type: "text", text: "Resolved vitalik.base.eth → 0xd8dA…6045. Approve to send:" }, + { delay: 600, type: "tool", tool: { server: "base-account", action: "send", args: { to: "jesse.base.eth", asset: "USDC", amount: "5" } } }, + { delay: 550, type: "text", text: "Resolved jesse.base.eth → 0xd8dA…6045. Approve to send:" }, { delay: 250, type: "approval", url: "keys.coinbase.com/approve/req_a4f7c2" }, - { delay: 1100, type: "confirm", text: "Sent 5 USDC to vitalik.base.eth" }, + { delay: 1100, type: "confirm", text: "Sent 5 USDC to jesse.base.eth" }, ], }, { diff --git a/docs/snippets/x402PayDemo.jsx b/docs/snippets/x402PayDemo.jsx index b7f7384e4..4e8b41f2d 100644 --- a/docs/snippets/x402PayDemo.jsx +++ b/docs/snippets/x402PayDemo.jsx @@ -1,81 +1,236 @@ -import { useState, useEffect, useRef } from "react"; export const X402PayDemo = () => { - const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8", warn: "#fb923c" }; - - const steps = [ - { delay: 400, lines: [{ t: "> Send 5 USDC to bob.base.eth", c: "active" }] }, - { delay: 500, lines: [ - { t: " ── send() ─────────────────────────────────", c: "dim" }, - { t: " recipient: bob.base.eth amount: 5 asset: USDC", c: "muted" }, - ]}, - { delay: 650, lines: [ - { t: " ── approval required ──────────────────────", c: "warn" }, - { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, - { t: ' requestId: "req_abc123"', c: "muted" }, - ]}, - { delay: 500, lines: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }] }, - { delay: 1100, lines: [{ t: " ← user opened and approved ✓", c: "success" }] }, - { delay: 500, lines: [ - { t: " ── get_request_status ─────────────────────", c: "dim" }, - { t: ' requestId: "req_abc123"', c: "muted" }, - ]}, - { delay: 500, lines: [ - { t: ' status: "confirmed"', c: "success" }, - { t: ' txHash: "0xf7e3...9a12"', c: "success" }, - ]}, - { delay: 300, lines: [{ t: "", c: "dim" }, { t: " ✓ 5 USDC sent to bob.base.eth", c: "success" }] }, + const sans = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"; + const serif = "'Tiempos Headline','Iowan Old Style','Source Serif Pro',ui-serif,Georgia,serif"; + const mono = "ui-monospace,'SF Mono','Cascadia Code',Menlo,Monaco,Consolas,monospace"; + + const c = { + bg: "#1f1e1d", header: "#262624", border: "#34322f", inputBg: "#2a2926", + text: "#f5f4ed", body: "#e8e4dc", muted: "#a8a39d", dim: "#6b6663", + accent: "#D97757", bubble: "#2c2b28", bubbleText: "#f5f4ed", + code: "#e89972", codeBg: "rgba(217,119,87,0.12)", + toolBg: "#272622", toolBorder: "#3a3835", success: "#a3c585", + }; + + const examples = [ + { + prompt: "Sign this message: I accept the terms of service", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "base-account", action: "sign", args: { type: "personal_sign", message: "I accept the terms of service" } } }, + { delay: 500, type: "text", text: "Signing with your Base Account. Approve to generate signature:" }, + { delay: 250, type: "approval", url: "keys.coinbase.com/approve/req_sign01" }, + { delay: 1100, type: "confirm", text: "Signed · sig 0x4f2a…c38e9b…8c91" }, + ], + }, + { + prompt: "Sign in to this app with my Base Account", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "base-account", action: "sign", args: { type: "personal_sign", standard: "EIP-4361", domain: "app.example.com" } } }, + { delay: 500, type: "text", text: "Signing in to app.example.com using Sign-In with Ethereum (SIWE):" }, + { delay: 250, type: "approval", url: "keys.coinbase.com/approve/req_siwe01" }, + { delay: 1100, type: "confirm", text: "Signed in to app.example.com · session valid" }, + ], + }, + { + prompt: "Sign a Uniswap permit2 authorization", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "base-account", action: "sign", args: { type: "EIP-712", standard: "permit2", token: "USDC", spender: "Uniswap" } } }, + { delay: 500, type: "text", text: "Signing typed permit2 data for Uniswap. Review and approve:" }, + { delay: 250, type: "approval", url: "keys.coinbase.com/approve/req_permit01" }, + { delay: 1100, type: "confirm", text: "Permit2 signed · Uniswap can spend up to 1000 USDC" }, + ], + }, ]; - const [lines, setLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const ref = useRef(null); - - useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); - useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]); - - const reset = () => { setLines([]); setRunning(false); setDone(false); }; - const run = () => { - if (running || done) return; - setRunning(true); - let i = 0; - const next = () => { - if (i >= steps.length) { setRunning(false); setDone(true); return; } - setTimeout(() => { setLines(p => [...p, ...steps[i].lines]); i++; next(); }, steps[i].delay); - }; - next(); + const [activeIdx, setActiveIdx] = useState(null); + const [eventIdx, setEventIdx] = useState(0); + const scrollRef = useRef(null); + const timersRef = useRef([]); + + const clearTimers = () => { timersRef.current.forEach(clearTimeout); timersRef.current = []; }; + + useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [eventIdx, activeIdx]); + useEffect(() => () => clearTimers(), []); + + const pick = (idx) => { + if (activeIdx !== null) return; + setActiveIdx(idx); + setEventIdx(0); + clearTimers(); + let cumulative = 0; + examples[idx].events.forEach((e, i) => { + cumulative += e.delay; + timersRef.current.push(setTimeout(() => setEventIdx(i + 1), cumulative)); + }); }; - const renderLine = (item, i) => { - if (!item.t) return
; - return
{item.t}
; + const reset = () => { clearTimers(); setActiveIdx(null); setEventIdx(0); }; + const ex = activeIdx !== null ? examples[activeIdx] : null; + + const TrafficLights = () => ( +
+ + + +
+ ); + + const UserBubble = ({ children }) => ( +
+
{children}
+
+ ); + + const ToolCall = ({ tool, completed }) => ( +
+
+ + {completed + ? + : } + + + {tool.server} + · + {tool.action} + ( + {Object.entries(tool.args).map(([k, v], i, arr) => ( + {k}: "{v}"{i < arr.length - 1 && , } + ))} + ) + +
+
+ ); + + const Thinking = () => ( +
+ + {[0, 1, 2].map(i => )} + + Thinking +
+ ); + + const ResponseText = ({ children, top }) => ( +
{children}
+ ); + + const ApprovalLink = ({ url }) => ( +
+ + + {url} + +
+ ); + + const Confirm = ({ text }) => ( +
+ + {text} +
+ ); + + const ChipBtn = ({ onClick, children }) => { + const [hover, setHover] = useState(false); + return ( + + ); + }; + + const renderEvents = () => { + if (!ex) return null; + const shown = ex.events.slice(0, eventIdx); + return shown.map((event, i) => { + if (event.type === "thinking") { + if (i < shown.length - 1) return null; + return ; + } + if (event.type === "tool") { + const hasLater = shown.slice(i + 1).some(e => e.type !== "thinking"); + return ; + } + if (event.type === "text") return {event.text}; + if (event.type === "approval") return ; + if (event.type === "confirm") return ; + return null; + }); }; return ( -
-
-
- {">"}_ -
- Approval Mode +
+ + +
+ + Base wallet +
- + {activeIdx !== null && ( + + )}
-
-
Terminal
-
- {lines.map(renderLine)} - {running &&
{"▋"}
} -
+ +
+ {!ex && ( +
+
+ Sign messages and typed data once mcp.base.org is connected: +
+
+ {examples.map((e, i) => pick(i)}>{e.prompt})} +
+
+ )} + {ex && <>{ex.prompt}{renderEvents()}}
-
- {!running && !done && } - {done && } + +
+
+ + Write a message... + Sonnet 4.6 + +
+
+ Demo · Every signature requires your approval at keys.coinbase.com +
); From 36dd10f6c0c64aa2e9e17390d5f201c837727db7 Mon Sep 17 00:00:00 2001 From: Youssef Date: Tue, 19 May 2026 00:00:42 +0100 Subject: [PATCH 07/36] update manual integration --- docs/ai-agents/quickstart.mdx | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index 3dab0d5ff..a72f22eee 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -29,26 +29,7 @@ Connect `mcp.base.org` to your AI assistant, then send your first prompt. - **Name**: `Base` - **Remote MCP server URL**: `https://mcp.base.org` 4. Click **Add** - - **Claude Desktop config file** — if you prefer to configure manually, open **Settings → Developer → Edit Config** and add: - - | Platform | Config path | - |----------|-------------| - | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` | - | Windows | `%APPDATA%\Claude\claude_desktop_config.json` | - | Linux | `~/.config/Claude/claude_desktop_config.json` | - - ```json claude_desktop_config.json - { - "mcpServers": { - "base": { - "url": "https://mcp.base.org" - } - } - } - ``` - - Save and restart Claude Desktop. + [![Add to ChatGPT](https://img.shields.io/badge/Add%20to%20ChatGPT-1F1F1F?style=for-the-badge)](https://chatgpt.com/#settings/Connectors) From 47fb1680eb41305d227fdd4520d83c5b304673d2 Mon Sep 17 00:00:00 2001 From: Youssef Date: Tue, 19 May 2026 00:04:17 +0100 Subject: [PATCH 08/36] update skills --- docs/ai-agents/quickstart.mdx | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index a72f22eee..6e5ae743e 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -1,14 +1,12 @@ --- title: "Quickstart" -description: "Connect Base MCP to your AI assistant in under 2 minutes" +description: "Connect Base MCP to your agent in under 2 minutes" keywords: ["Base MCP quickstart", "mcp.base.org setup", "Claude Desktop MCP", "ChatGPT MCP", "Claude Code MCP wallet", "Cursor MCP", "Codex MCP", "Hermes MCP"] --- import { WalletSetupDemo } from "/snippets/WalletSetupDemo.jsx" import { AuthApprovalDemo } from "/snippets/AuthApprovalDemo.jsx" -Connect `mcp.base.org` to your AI assistant, then send your first prompt. - ## Demo @@ -146,37 +144,32 @@ Connect `mcp.base.org` to your AI assistant, then send your first prompt. See [Skills in ChatGPT](https://help.openai.com/en/articles/20001066-skills-in-chatgpt) for details. - Install the skill to your global skills directory: - ```bash Terminal - curl -o ~/.claude/skills/base-mcp.md \ - https://raw.githubusercontent.com/base/skills/main/base-mcp.md + npx skills add base/skills --skill base-mcp -a claude-code ``` - The skill loads automatically in your next session. Invoke it with `/base-mcp` inside any Claude Code conversation. + Installs to `~/.claude/skills/base-mcp/`. The skill loads on your next session — Claude Code will use it automatically when wallet questions come up. - Install from the community skill registry: - ```bash Terminal - $skill-installer base-mcp + npx skills add base/skills --skill base-mcp -a codex ``` + + Installs to `~/.codex/skills/base-mcp/`. Codex picks it up automatically on the next run. - Add the skill as a global Cursor rule: - ```bash Terminal - curl -o ~/.cursor/rules/base-mcp.mdc \ - https://raw.githubusercontent.com/base/skills/main/base-mcp.mdc + npx skills add base/skills --skill base-mcp -a cursor ``` + + Installs to `~/.cursor/skills/base-mcp/`. Cursor picks it up automatically — invoke it in agent chat for any wallet workflow. - Install the skill to your Hermes skills directory: - ```bash Terminal - curl -o ~/.hermes/skills/base-mcp.md \ - https://raw.githubusercontent.com/base/skills/main/base-mcp.md + hermes skills install github:base/skills/base-mcp ``` + + Installs to `~/.hermes/skills/base-mcp/`. Run `/reload-skills` inside Hermes (or restart the session) and it's available immediately. From a884157a4cc6505b3290d25d4df4e73a7ef706de Mon Sep 17 00:00:00 2001 From: Youssef Date: Tue, 19 May 2026 00:11:55 +0100 Subject: [PATCH 09/36] update list --- docs/snippets/AuthApprovalDemo.jsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/snippets/AuthApprovalDemo.jsx b/docs/snippets/AuthApprovalDemo.jsx index afa5cee53..bfd6274b4 100644 --- a/docs/snippets/AuthApprovalDemo.jsx +++ b/docs/snippets/AuthApprovalDemo.jsx @@ -24,9 +24,7 @@ export const AuthApprovalDemo = ({ client = "Claude" }) => { const permissions = [ { label: "View address, balances & activity." }, - { label: "Request approval for sends and swaps." }, - { label: "Sign messages and typed data on request." }, - { label: "Read onchain data on Base." }, + { label: "Request approval for transactions." } ]; const EyeIcon = () => ( From 9e4e9a361192f7c3313c17cf176ffa740a66670d Mon Sep 17 00:00:00 2001 From: Youssef Date: Tue, 19 May 2026 15:59:58 +0100 Subject: [PATCH 10/36] update check balance guide and demo --- docs/ai-agents/guides/check-balance.mdx | 7 +++---- docs/snippets/DataFetchingDemo.jsx | 16 +++++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/ai-agents/guides/check-balance.mdx b/docs/ai-agents/guides/check-balance.mdx index 8cc99b4ce..92caeca2a 100644 --- a/docs/ai-agents/guides/check-balance.mdx +++ b/docs/ai-agents/guides/check-balance.mdx @@ -15,7 +15,7 @@ Show me my wallets ``` ```text -What's my USDC balance on Base? +What is my USDC balance? ``` ```text @@ -23,18 +23,17 @@ Show my full portfolio ``` ```text -What's the balance of 0x1234...abcd? +What tokens do I have in my wallet? ``` ## How it works **`get_wallets`** — lists all wallets in your wallet group (your Base Account plus any agent wallets). Shows which wallets are active in the current session (`inSession: true`). -**`get_portfolio`** — returns portfolio value and per-asset breakdown. Works for any public address — not just your own. +**`get_portfolio`** — returns portfolio value and per-asset breakdown for your connected wallet. | Parameter | What it does | |-----------|-------------| -| `address` | Address to query — defaults to your Base Account | | `chain` | Filter by chain: `base` or `ethereum` | | `query` | Filter by token name or symbol (e.g. "USDC") | | `includePnl` | Include unrealized/realized P&L per asset | diff --git a/docs/snippets/DataFetchingDemo.jsx b/docs/snippets/DataFetchingDemo.jsx index 354322925..eb3d4d362 100644 --- a/docs/snippets/DataFetchingDemo.jsx +++ b/docs/snippets/DataFetchingDemo.jsx @@ -28,16 +28,18 @@ export const DataFetchingDemo = () => { ], }, { - prompt: "Check the balance of jesse.base.eth", + prompt: "What tokens do I have in my wallet?", events: [ { delay: 380, type: "thinking" }, - { delay: 550, type: "tool", tool: { server: "base-account", action: "get_portfolio", args: { address: "jesse.base.eth", chain: "base" } } }, - { delay: 600, type: "text", text: "Balances for jesse.base.eth (0xd8dA…6045) on Base:" }, + { delay: 550, type: "tool", tool: { server: "base-account", action: "get_wallets", args: {} } }, + { delay: 600, type: "tool", tool: { server: "base-account", action: "get_portfolio", args: { chain: "base" } } }, + { delay: 500, type: "text", text: "Tokens in your wallet on Base:" }, { delay: 250, type: "rows", rows: [ - { token: "ETH", amount: "1,842.14", value: "$6.63M" }, - { token: "USDC", amount: "28,450.00", value: "$28.4K" }, - { token: "DAI", amount: "10,000.00", value: "$10.0K" }, + { token: "USDC", amount: "245.80", value: "$245.80" }, + { token: "ETH", amount: "0.0412", value: "$148.33" }, + { token: "WETH", amount: "0.0100", value: "$36.02" }, ]}, + { delay: 400, type: "confirm", text: "3 tokens found on Base" }, ], }, { @@ -226,7 +228,7 @@ export const DataFetchingDemo = () => { {!ex && (
- Check any wallet's balance once mcp.base.org is connected: + Check your wallet balance once mcp.base.org is connected:
{examples.map((e, i) => pick(i)}>{e.prompt})} From f3380105232540049ef5f22ba301ecb6d57f58a4 Mon Sep 17 00:00:00 2001 From: Youssef Date: Tue, 19 May 2026 19:27:36 +0100 Subject: [PATCH 11/36] update landing demo --- docs/snippets/WalletSetupDemo.jsx | 380 +++++++++++++++++++++++++++--- 1 file changed, 346 insertions(+), 34 deletions(-) diff --git a/docs/snippets/WalletSetupDemo.jsx b/docs/snippets/WalletSetupDemo.jsx index 11c6ecbbb..15bbb38b7 100644 --- a/docs/snippets/WalletSetupDemo.jsx +++ b/docs/snippets/WalletSetupDemo.jsx @@ -23,9 +23,6 @@ export const WalletSetupDemo = () => { success: "#a3c585", }; - // Each example is a sequence of events. Each event reveals one block. - // Block types: thinking, tool, text, rows, approval, confirm - // (thinking auto-hides once the next event renders) const examples = [ { prompt: "Send 5 USDC to jesse.base.eth", @@ -33,7 +30,7 @@ export const WalletSetupDemo = () => { { delay: 380, type: "thinking" }, { delay: 600, type: "tool", tool: { server: "base-account", action: "send", args: { to: "jesse.base.eth", asset: "USDC", amount: "5" } } }, { delay: 550, type: "text", text: "Resolved jesse.base.eth → 0xd8dA…6045. Approve to send:" }, - { delay: 250, type: "approval", url: "keys.coinbase.com/approve/req_a4f7c2" }, + { delay: 250, type: "approval", preview: { type: "send", asset: "USDC", amount: "5", usdValue: "$5.00", to: "jesse.base.eth" } }, { delay: 1100, type: "confirm", text: "Sent 5 USDC to jesse.base.eth" }, ], }, @@ -49,7 +46,7 @@ export const WalletSetupDemo = () => { { token: "Uniswap v3 (best)", amount: "179.41 USDC", value: "0.05% fee · slippage 0.12%" }, ]}, { delay: 700, type: "tool", tool: { server: "uniswap-v3", action: "prepare_swap", args: { route: "ETH→USDC", min_out: "179.20 USDC" } } }, - { delay: 450, type: "approval", url: "keys.coinbase.com/approve/req_8c2e4d" }, + { delay: 450, type: "approval", preview: { type: "swap", fromAsset: "ETH", fromAmount: "0.05", fromUsd: "~$127.00", toAsset: "USDC", toAmount: "179.41", toUsd: "~$179.41" } }, { delay: 1100, type: "confirm", text: "Swapped 0.05 ETH → 179.41 USDC on Uniswap v3" }, ], }, @@ -66,16 +63,17 @@ export const WalletSetupDemo = () => { { token: "Moonwell · USDC market", amount: "5.13% APY", value: "$41.2M supplied" }, ]}, { delay: 700, type: "tool", tool: { server: "morpho", action: "prepare_deposit", args: { vault: "Steakhouse USDC", amount: "100 USDC" } } }, - { delay: 450, type: "approval", url: "keys.coinbase.com/approve/req_b9f2a1" }, + { delay: 450, type: "approval", preview: { type: "deposit", asset: "USDC", amount: "100", usdValue: "~$100.00", vault: "Steakhouse USDC", apy: "8.42%" } }, { delay: 1100, type: "confirm", text: "Deposited 100 USDC into Steakhouse USDC · earning 8.42% APY" }, ], }, ]; - const [activeIdx, setActiveIdx] = useState(null); - const [eventIdx, setEventIdx] = useState(0); - const scrollRef = useRef(null); - const timersRef = useRef([]); + const [activeIdx, setActiveIdx] = useState(null); + const [eventIdx, setEventIdx] = useState(0); + const [modalPreview, setModalPreview] = useState(null); + const scrollRef = useRef(null); + const timersRef = useRef([]); const clearTimers = () => { timersRef.current.forEach(clearTimeout); timersRef.current = []; }; @@ -94,10 +92,39 @@ export const WalletSetupDemo = () => { }); }; - const reset = () => { clearTimers(); setActiveIdx(null); setEventIdx(0); }; + const reset = () => { clearTimers(); setActiveIdx(null); setEventIdx(0); setModalPreview(null); }; + + const handleConfirm = () => { + setModalPreview(null); + clearTimers(); + if (activeIdx !== null) setEventIdx(examples[activeIdx].events.length); + }; const ex = activeIdx !== null ? examples[activeIdx] : null; + // ----- Token avatars ----- + + const tokenColor = (ticker) => { + if (!ticker) return c.accent; + const t = ticker.toUpperCase(); + if (t === "USDC") return "#2775CA"; + if (t === "ETH") return "#627EEA"; + return c.accent; + }; + + const TokenAvatar = ({ ticker }) => ( +
+ + {(ticker || "??").slice(0, 2).toUpperCase()} + +
+ ); + // ----- UI bits ----- const TrafficLights = () => ( @@ -191,24 +218,34 @@ export const WalletSetupDemo = () => {
); - const ApprovalLink = ({ url }) => ( -
- - - - - - {url} - -
- ); + const ApprovalButton = ({ preview, onApprove }) => { + const [hover, setHover] = useState(false); + return ( +
+ +
+ ); + }; const Confirm = ({ text }) => (
{ ); }; + // ----- Transaction modal (compact, high-fidelity Coinbase Wallet "Review") ----- + + const TxModal = ({ preview, onConfirm, onCancel }) => { + const mbg = "#0a0a0a"; + const mcard = "#1a1816"; + const mhair = "#1f1d1b"; + const mwhite = "#ffffff"; + const mvalue = "#a09b95"; + const msub = "#7a7470"; + + // Wallet avatar — wow-face emoji style in a blue gradient circle + const CBAvatar = () => ( +
+ + + +
+ ); + + const BigTokenAvatar = ({ ticker }) => ( +
+ + {(ticker || "??").slice(0, 2).toUpperCase()} + +
+ ); + + const SmallTokenAvatar = ({ ticker }) => ( +
+ + {(ticker || "??").slice(0, 2).toUpperCase()} + +
+ ); + + const renderPreview = () => { + if (preview.type === "send") return ( +
+
+ +
+
+ {preview.amount} {preview.asset} +
+
+ {preview.usdValue} +
+
+
+ To + {preview.to} +
+
+ ); + + if (preview.type === "swap") return ( +
+
+ +
+
You send
+
+ {preview.fromAmount} {preview.fromAsset} +
+
+
{preview.fromUsd}
+
+
+
+ + + +
+
+
+ +
+
You receive
+
+ {preview.toAmount} {preview.toAsset} +
+
+
{preview.toUsd}
+
+
+ ); + + if (preview.type === "deposit") return ( +
+
+ +
+
You deposit
+
+ {preview.amount} {preview.asset} +
+
+
{preview.usdValue}
+
+
+ Into +
+
{preview.vault}
+
{preview.apy} APY
+
+
+
+ ); + + return null; + }; + + const FieldRow = ({ label, right }) => ( +
+ {label} +
{right}
+
+ ); + + return ( +
+
e.stopPropagation()} + style={{ + background: mbg, + borderRadius: 16, + border: `1px solid #1f1d1b`, + width: 320, maxWidth: "100%", + maxHeight: "calc(100vh - 32px)", + overflowY: "auto", + boxShadow: "0 24px 80px rgba(0,0,0,0.85)", + }} + > + {/* Header */} +
+ Review + + + + +
+ + {/* Demo banner — single line */} +
+ + + + + DEMO · Not a real transaction + +
+ + {/* Asset preview card */} +
+ {renderPreview()} +
+ + {/* Field rows */} +
+ + + 0x71Dc…7244 + + } + /> + + + 0x71Dc…7244 + + + } + /> + +
+ Base + + } + /> + {"< $0.01"}} + /> +
+ + {/* Buttons */} +
+ + +
+
+
+ ); + }; + // Render the events shown so far for the active example const renderEvents = () => { if (!ex) return null; const shown = ex.events.slice(0, eventIdx); return shown.map((event, i) => { - // Hide thinking once any later event has appeared if (event.type === "thinking") { if (i < shown.length - 1) return null; return ; } if (event.type === "tool") { - // Mark as completed once any later non-thinking event has appeared const hasLater = shown.slice(i + 1).some(e => e.type !== "thinking"); return ; } if (event.type === "text") return {event.text}; if (event.type === "rows") return ; - if (event.type === "approval") return ; + if (event.type === "approval") return ; if (event.type === "confirm") return ; return null; }); @@ -274,6 +578,7 @@ export const WalletSetupDemo = () => { return (
{ .wsd-row { gap: 12px; flex-wrap: nowrap; } .wsd-row-token { min-width: 200px; } .wsd-bubble { max-width: 78%; font-size: 14px; } - .wsd-approval { font-size: 12.5px; } .wsd-chip { padding: 16px 18px; font-size: 15px; } .wsd-empty-text { font-size: 16px; } .wsd-footnote { font-size: 11px; } @@ -302,7 +606,6 @@ export const WalletSetupDemo = () => { .wsd-row { flex-wrap: wrap; gap: 4px 10px; } .wsd-row-token { min-width: 100%; flex: 1 1 100%; } .wsd-bubble { max-width: 88%; font-size: 13.5px; } - .wsd-approval { font-size: 11.5px; word-break: break-all; } .wsd-chip { padding: 14px 14px; font-size: 14px; } .wsd-empty-text { font-size: 14.5px; } .wsd-footnote { font-size: 10.5px; } @@ -311,6 +614,15 @@ export const WalletSetupDemo = () => { } `} + {/* Transaction approval modal */} + {modalPreview && ( + setModalPreview(null)} + /> + )} + {/* Header */}
Date: Tue, 19 May 2026 20:41:35 +0100 Subject: [PATCH 12/36] update demos --- docs/snippets/AcceptingPaymentsDemo.jsx | 531 ++++++++++++++++- docs/snippets/AgentPaymentDemo.jsx | 527 +++++++++++++++- docs/snippets/TradeExecutionDemo.jsx | 531 ++++++++++++++++- docs/snippets/TradingQuickstartDemo.jsx | 531 ++++++++++++++++- docs/snippets/WalletSetupDemo.jsx | 759 +++++++++++++++--------- docs/snippets/x402PayDemo.jsx | 531 ++++++++++++++++- 6 files changed, 3013 insertions(+), 397 deletions(-) diff --git a/docs/snippets/AcceptingPaymentsDemo.jsx b/docs/snippets/AcceptingPaymentsDemo.jsx index a177932d2..ec5a22cb8 100644 --- a/docs/snippets/AcceptingPaymentsDemo.jsx +++ b/docs/snippets/AcceptingPaymentsDemo.jsx @@ -1,4 +1,3 @@ - export const AcceptingPaymentsDemo = () => { const sans = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"; const serif = "'Tiempos Headline','Iowan Old Style','Source Serif Pro',ui-serif,Georgia,serif"; @@ -12,6 +11,494 @@ export const AcceptingPaymentsDemo = () => { toolBg: "#272622", toolBorder: "#3a3835", success: "#a3c585", }; + + + + // Shared Coinbase Wallet "Review" modal + Approve Transaction button used + // across the ai-agents demos. Supports asset-transfer previews (send, swap, + // deposit, borrow, repay) and signing previews (sign-message, sign-siwe, + // sign-permit). Positioned absolute inside the parent demo container so it + // doesn't fight with the Mintlify navbar's z-index. + + const ACCENT = "#D97757"; + + const tokenBg = (ticker) => { + if (!ticker) return ACCENT; + const t = ticker.toUpperCase(); + if (t === "USDC") return "#2775CA"; + if (t === "ETH" || t === "WETH") return "#627EEA"; + if (t === "CBBTC" || t === "BTC") return "#F7931A"; + if (t === "DEGEN") return "#A06CFF"; + if (t === "POL") return "#8247E5"; + return ACCENT; + }; + + const tokenGlow = (ticker) => { + if (!ticker) return "rgba(217,119,87,0.14)"; + const t = ticker.toUpperCase(); + if (t === "USDC") return "rgba(39,117,202,0.14)"; + if (t === "ETH" || t === "WETH") return "rgba(98,126,234,0.14)"; + if (t === "CBBTC" || t === "BTC") return "rgba(247,147,26,0.14)"; + if (t === "DEGEN") return "rgba(160,108,255,0.14)"; + return "rgba(217,119,87,0.14)"; + }; + + const BigTokenAvatar = ({ ticker }) => ( +
+ + {(ticker || "??").slice(0, 2).toUpperCase()} + +
+ ); + + const SmallTokenAvatar = ({ ticker }) => ( +
+ + {(ticker || "??").slice(0, 2).toUpperCase()} + +
+ ); + + // Wallet avatar — wow-face emoji style in a blue gradient circle + const CBAvatar = () => ( +
+ + + +
+ ); + + // Sign-icon avatar for signing flows — pen-on-paper in a purple gradient circle + const SignAvatar = () => ( +
+ + + +
+ ); + + const ApprovalButton = ({ preview, onApprove, label }) => { + const [hover, setHover] = useState(false); + return ( +
+ +
+ ); + }; + + const TxModal = ({ preview, onConfirm, onCancel }) => { + const mbg = "#0a0a0a"; + const mcard = "#1a1816"; + const mhair = "#1f1d1b"; + const mwhite = "#ffffff"; + const mvalue = "#a09b95"; + const msub = "#7a7470"; + + const isSign = preview.type && preview.type.startsWith("sign"); + + const renderPreview = () => { + if (preview.type === "send") return ( +
+
+ +
+
+ {preview.amount} {preview.asset} +
+ {preview.usdValue && ( +
+ {preview.usdValue} +
+ )} +
+
+ To + {preview.to} +
+
+ ); + + if (preview.type === "swap") return ( +
+
+ +
+
You send
+
+ {preview.fromAmount} {preview.fromAsset} +
+
+ {preview.fromUsd && ( +
{preview.fromUsd}
+ )} +
+
+
+ + + +
+
+
+ +
+
You receive
+
+ {preview.toAmount} {preview.toAsset} +
+
+ {preview.toUsd && ( +
{preview.toUsd}
+ )} +
+
+ ); + + if (preview.type === "deposit") return ( +
+
+ +
+
You deposit
+
+ {preview.amount} {preview.asset} +
+
+ {preview.usdValue && ( +
{preview.usdValue}
+ )} +
+
+ Into +
+
{preview.vault}
+ {preview.apy && ( +
{preview.apy} APY
+ )} +
+
+
+ ); + + if (preview.type === "borrow") return ( +
+
+ +
+
Supply collateral
+
+ {preview.collateralAmount} {preview.collateralAsset} +
+
+
+
+ +
+
You borrow
+
+ {preview.loanAmount} {preview.loanAsset} +
+
+
+ {preview.healthFactor && ( +
+ Health factor + {preview.healthFactor} +
+ )} +
+ ); + + if (preview.type === "repay") return ( +
+
+ +
+
You repay
+
+ {preview.amount} {preview.asset} +
+
+ {preview.usdValue && ( +
{preview.usdValue}
+ )} +
+
+ To market + {preview.market} +
+
+ ); + + if (preview.type === "sign-message") return ( +
+
+ +
+
+ Sign message +
+
+ personal_sign +
+
+ "{preview.message}" +
+
+ ); + + if (preview.type === "sign-siwe") return ( +
+
+ +
+
+ Sign in with Ethereum +
+
+ EIP-4361 · session login +
+
+
+ Domain + {preview.domain} +
+
+ ); + + if (preview.type === "sign-permit") return ( +
+
+ +
+
+ Approve token spending +
+
+ EIP-712 · Permit2 +
+
+
+ Token +
+ + {preview.token} +
+
+
+ Spender + {preview.spender} +
+ {preview.amount && ( +
+ Allowance + {preview.amount} +
+ )} +
+ ); + + return null; + }; + + const FieldRow = ({ label, right }) => ( +
+ {label} +
{right}
+
+ ); + + return ( +
+
e.stopPropagation()} + style={{ + background: mbg, + borderRadius: 16, + border: `1px solid #1f1d1b`, + width: 320, maxWidth: "100%", + maxHeight: "calc(100% - 8px)", + overflowY: "auto", + boxShadow: "0 24px 80px rgba(0,0,0,0.85)", + }} + > + {/* Header */} +
+ + {isSign ? "Sign" : "Review"} + + + + + +
+ + {/* Demo banner */} +
+ + + + + DEMO · Not a real {isSign ? "signature" : "transaction"} + +
+ + {/* Preview */} +
+ {renderPreview()} +
+ + {/* Field rows */} +
+ + + 0x71Dc…7244 + + } + /> + {!isSign && ( + + + 0x71Dc…7244 + + + } + /> + )} + +
+ Base + + } + /> + {!isSign && ( + {"< $0.01"}} + /> + )} +
+ + {/* Buttons */} +
+ + +
+
+
+ ); + }; + + const examples = [ { prompt: "Find the best USDC vault on Base and deposit 100 USDC", @@ -26,7 +513,7 @@ export const AcceptingPaymentsDemo = () => { ]}, { delay: 500, type: "tool", tool: { server: "morpho", action: "prepare_deposit", args: { vault: "Steakhouse USDC", amount: "100 USDC" } } }, { delay: 350, type: "tool", tool: { server: "base-account", action: "send_calls", args: { chainId: "0x2105", calls: "[approve, deposit]" } } }, - { delay: 450, type: "approval", url: "keys.coinbase.com/approve/req_b9f2a1" }, + { delay: 450, type: "approval", preview: { type: "deposit", asset: "USDC", amount: "100", usdValue: "~$100.00", vault: "Steakhouse USDC", apy: "8.42%" } }, { delay: 1100, type: "confirm", text: "Deposited 100 USDC into Steakhouse USDC · earning 8.42% APY" }, ], }, @@ -38,7 +525,7 @@ export const AcceptingPaymentsDemo = () => { { delay: 500, type: "text", text: "Found Morpho ETH/USDC market on Base. Batching supply + borrow..." }, { delay: 500, type: "tool", tool: { server: "morpho", action: "prepare_supply_collateral", args: { asset: "ETH", amount: "0.5", borrow: "1000 USDC" } } }, { delay: 350, type: "tool", tool: { server: "base-account", action: "send_calls", args: { chainId: "0x2105", calls: "[supplyCollateral, borrow]" } } }, - { delay: 450, type: "approval", url: "keys.coinbase.com/approve/req_m3k2p9" }, + { delay: 450, type: "approval", preview: { type: "borrow", collateralAsset: "ETH", collateralAmount: "0.5", loanAsset: "USDC", loanAmount: "1000", healthFactor: "2.1" } }, { delay: 1100, type: "confirm", text: "Supplied 0.5 ETH · borrowed 1000 USDC · health factor 2.1" }, ], }, @@ -50,14 +537,15 @@ export const AcceptingPaymentsDemo = () => { { delay: 500, type: "text", text: "You owe 1002.14 USDC including accrued interest. Preparing full repayment..." }, { delay: 500, type: "tool", tool: { server: "morpho", action: "prepare_repay", args: { amount: "1002.14 USDC", market: "ETH/USDC" } } }, { delay: 350, type: "tool", tool: { server: "base-account", action: "send_calls", args: { chainId: "0x2105", calls: "[approve, repayAll]" } } }, - { delay: 450, type: "approval", url: "keys.coinbase.com/approve/req_r7d4s1" }, + { delay: 450, type: "approval", preview: { type: "repay", asset: "USDC", amount: "1002.14", usdValue: "~$1,002.14", market: "Morpho ETH/USDC" } }, { delay: 1100, type: "confirm", text: "Repaid 1002.14 USDC · Morpho position closed" }, ], }, ]; - const [activeIdx, setActiveIdx] = useState(null); - const [eventIdx, setEventIdx] = useState(0); + const [activeIdx, setActiveIdx] = useState(null); + const [eventIdx, setEventIdx] = useState(0); + const [modalPreview, setModalPreview] = useState(null); const scrollRef = useRef(null); const timersRef = useRef([]); @@ -72,13 +560,22 @@ export const AcceptingPaymentsDemo = () => { setEventIdx(0); clearTimers(); let cumulative = 0; - examples[idx].events.forEach((e, i) => { - cumulative += e.delay; + const events = examples[idx].events; + for (let i = 0; i < events.length; i++) { + cumulative += events[i].delay; timersRef.current.push(setTimeout(() => setEventIdx(i + 1), cumulative)); - }); + if (events[i].type === "approval") break; + } + }; + + const reset = () => { clearTimers(); setActiveIdx(null); setEventIdx(0); setModalPreview(null); }; + + const handleConfirm = () => { + setModalPreview(null); + clearTimers(); + if (activeIdx !== null) setEventIdx(examples[activeIdx].events.length); }; - const reset = () => { clearTimers(); setActiveIdx(null); setEventIdx(0); }; const ex = activeIdx !== null ? examples[activeIdx] : null; const TrafficLights = () => ( @@ -143,15 +640,6 @@ export const AcceptingPaymentsDemo = () => {
); - const ApprovalLink = ({ url }) => ( -
- - - {url} - -
- ); - const Confirm = ({ text }) => (
@@ -184,14 +672,15 @@ export const AcceptingPaymentsDemo = () => { } if (event.type === "text") return {event.text}; if (event.type === "rows") return ; - if (event.type === "approval") return ; + if (event.type === "approval") return ; if (event.type === "confirm") return ; return null; }); }; return ( -
+
+ {modalPreview && setModalPreview(null)} />} - -
- - CDP Agentic Wallet · x402 - -
- {activeIdx !== null && ( - - )} -
- -
- {!ex && ( -
-
- Try x402 agent payments with the CDP Agentic Wallet: -
-
- {examples.map((e, i) => pick(i)}>{e.prompt})} -
-
- )} - {ex && <>{ex.prompt}{renderEvents()}} -
- -
-
- - Write a message... - Sonnet 4.6 - -
-
- Demo · x402 payments settle instantly on Base · no approval required -
-
-
- ); -}; diff --git a/docs/snippets/x402PayDemo.jsx b/docs/snippets/SignMessagesDemo.jsx similarity index 99% rename from docs/snippets/x402PayDemo.jsx rename to docs/snippets/SignMessagesDemo.jsx index 061e86ea6..1ca38f8ac 100644 --- a/docs/snippets/x402PayDemo.jsx +++ b/docs/snippets/SignMessagesDemo.jsx @@ -1,4 +1,4 @@ -export const X402PayDemo = () => { +export const SignMessagesDemo = () => { const sans = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"; const serif = "'Tiempos Headline','Iowan Old Style','Source Serif Pro',ui-serif,Georgia,serif"; const mono = "ui-monospace,'SF Mono','Cascadia Code',Menlo,Monaco,Consolas,monospace"; @@ -682,7 +682,7 @@ export const X402PayDemo = () => {
- Base wallet + Base MCP
{activeIdx !== null && ( diff --git a/docs/snippets/TradeExecutionDemo.jsx b/docs/snippets/TradeExecutionDemo.jsx index d9fdb97d8..7e9601b03 100644 --- a/docs/snippets/TradeExecutionDemo.jsx +++ b/docs/snippets/TradeExecutionDemo.jsx @@ -683,7 +683,7 @@ export const TradeExecutionDemo = () => {
- Base wallet + Base MCP
{activeIdx !== null && ( diff --git a/docs/snippets/TradingQuickstartDemo.jsx b/docs/snippets/TradingQuickstartDemo.jsx index 1b470063f..06e5c2a0a 100644 --- a/docs/snippets/TradingQuickstartDemo.jsx +++ b/docs/snippets/TradingQuickstartDemo.jsx @@ -707,7 +707,7 @@ export const TradingQuickstartDemo = () => {
- Base wallet + Base MCP
{activeIdx !== null && ( diff --git a/docs/snippets/WalletSetupDemo.jsx b/docs/snippets/WalletSetupDemo.jsx index 64555462e..b022bc88a 100644 --- a/docs/snippets/WalletSetupDemo.jsx +++ b/docs/snippets/WalletSetupDemo.jsx @@ -802,7 +802,7 @@ export const WalletSetupDemo = () => { }}> - Base wallet + Base MCP
From d1b0b38daa35141e4a240a1111bfb606e99bb457 Mon Sep 17 00:00:00 2001 From: Youssef Date: Wed, 20 May 2026 00:53:47 +0100 Subject: [PATCH 24/36] update chatgpt --- docs/ai-agents/quickstart.mdx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index a2de2ad38..b74085b01 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -142,12 +142,24 @@ import { AuthApprovalDemo } from "/snippets/AuthApprovalDemo.jsx" Claude activates the skill automatically when relevant to your prompt. See [Use skills in Claude](https://support.claude.com/en/articles/12512180-use-skills-in-claude) for details. + Skills in ChatGPT are only available on **Business, Enterprise, Edu, Teachers, and Healthcare** plans. If you're on another plan, use the **Copy prompt** option below — it works on any ChatGPT plan. + + **Option 1: Copy prompt (any plan)** + + + Read this skill and its plugins, check if I have the Base MCP installed, and onboard me by following the contents of this zip file: https://github.com/base/skills/raw/refs/heads/youssef/add-build-on-base-and-base-mcp/skills/base-mcp/base-mcp-v0.1.1.zip + + + Paste it into a new ChatGPT conversation. ChatGPT will fetch the skill, verify your Base MCP connection, and walk you through setup. + + **Option 2: Upload skill (Business, Enterprise, Edu, Teachers, Healthcare plans)** + Download for ChatGPT 1. Click the button above to download `base-mcp.zip` - 2. In ChatGPT, open **Settings → Skills** + 2. In ChatGPT, open [**Settings → Skills**](https://chatgpt.com/skills) 3. Click **Add skill** and upload the downloaded `base-mcp.zip` 4. Enable the skill for the conversations where you want it active From ab943ce3d81dec3f5c373311a77b48e8a3a77337 Mon Sep 17 00:00:00 2001 From: Youssef Date: Wed, 20 May 2026 00:55:58 +0100 Subject: [PATCH 25/36] update link --- docs/ai-agents/quickstart.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index b74085b01..dbf5d25ca 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -147,7 +147,7 @@ import { AuthApprovalDemo } from "/snippets/AuthApprovalDemo.jsx" **Option 1: Copy prompt (any plan)** - Read this skill and its plugins, check if I have the Base MCP installed, and onboard me by following the contents of this zip file: https://github.com/base/skills/raw/refs/heads/youssef/add-build-on-base-and-base-mcp/skills/base-mcp/base-mcp-v0.1.1.zip + Read this skill and its plugins, check if I have the Base MCP installed, and onboard me by following the contents of this zip file: `https://github.com/base/skills/raw/refs/heads/youssef/add-build-on-base-and-base-mcp/skills/base-mcp/base-mcp-v0.1.1.zip` Paste it into a new ChatGPT conversation. ChatGPT will fetch the skill, verify your Base MCP connection, and walk you through setup. From cbfd7d32995e65e718ed6c112c296f775bde4cd2 Mon Sep 17 00:00:00 2001 From: Youssef Date: Wed, 20 May 2026 16:47:36 +0100 Subject: [PATCH 26/36] update custom plugins --- docs/ai-agents/guides/agent-builder-codes.mdx | 1 - docs/ai-agents/index.mdx | 18 +++++----- docs/ai-agents/plugins/custom-plugin.mdx | 36 +++++-------------- docs/ai-agents/plugins/moonwell.mdx | 4 +-- docs/ai-agents/quickstart.mdx | 15 +++++--- docs/docs.json | 3 +- 6 files changed, 32 insertions(+), 45 deletions(-) diff --git a/docs/ai-agents/guides/agent-builder-codes.mdx b/docs/ai-agents/guides/agent-builder-codes.mdx index 89ff1f0fa..a7eec443a 100644 --- a/docs/ai-agents/guides/agent-builder-codes.mdx +++ b/docs/ai-agents/guides/agent-builder-codes.mdx @@ -2,7 +2,6 @@ title: "Builder Codes for Agents" description: "Register your agent on Base.dev and append a Builder Code to every transaction to measure onchain activity." keywords: ["builder code", "Base.dev", "ERC-8021", "attribution", "onchain activity", "agent attribution", "dataSuffix", "builder codes", "Base builder codes", "agent onchain"] -tag: "NEW" --- [Base.dev](https://base.dev) is the canonical registry for agents on Base. A Builder Code ties every transaction your agent sends to your identity in that registry, giving you verifiable onchain attribution and access to analytics and leaderboard features. diff --git a/docs/ai-agents/index.mdx b/docs/ai-agents/index.mdx index 866e39c8f..cd2b419a3 100644 --- a/docs/ai-agents/index.mdx +++ b/docs/ai-agents/index.mdx @@ -37,17 +37,17 @@ sequenceDiagram ## What you can do - - View your portfolio, token balances, and transaction history across any address on Base. - Send ETH or any ERC-20 token to addresses, ENS names, basenames, and cb.id names. Swap between any tokens via the Coinbase swap service directly from your assistant. - - Sign EIP-712 typed data and personal messages for authentication and protocol interactions. + + Sign EIP-712 typed data and plain messages for authentication and protocol interactions. + + + Batch multiple contract interactions into a single user approval. @@ -60,10 +60,10 @@ sequenceDiagram Step-by-step guides for sending, swapping, checking balance, and more. - - Extend with protocol plugins like Morpho for lending and vaults. + + Extend with protocol plugins like Moonwell for lending and vaults. - - Install the base-mcp skill to give your coding assistant deep context on MCP tools. + + Build your own plugin that produces unsigned calldata and executes through Base MCP's send_calls. diff --git a/docs/ai-agents/plugins/custom-plugin.mdx b/docs/ai-agents/plugins/custom-plugin.mdx index 94394795e..8bd024c2a 100644 --- a/docs/ai-agents/plugins/custom-plugin.mdx +++ b/docs/ai-agents/plugins/custom-plugin.mdx @@ -1,14 +1,14 @@ --- -title: "Custom Plugin" +title: "Build a Custom Plugin" description: "Build your own plugin that produces unsigned calldata and executes through Base MCP's send_calls" keywords: ["custom Base MCP plugin", "AI agent plugin Base", "send_calls custom protocol", "Base MCP web_request plugin", "build MCP plugin"] --- -A plugin is a markdown spec that teaches your assistant how to call an external API (or another MCP server), translate the response into a `calls` array, and execute it through Base MCP's `send_calls`. The official [Moonwell](/ai-agents/plugins/moonwell), [Morpho](/ai-agents/plugins/morpho), [Uniswap](/ai-agents/plugins/uniswap), and [Avantis](/ai-agents/plugins/avantis) plugins all follow the same shape — this page shows how to write your own. +A plugin is a markdown spec that teaches your assistant how to call an external API (or another MCP server), translate the response into a `calls` array, and execute it through Base MCP's `send_calls`. Examples include [Moonwell](/ai-agents/plugins/moonwell), [Morpho](/ai-agents/plugins/morpho), [Uniswap](/ai-agents/plugins/uniswap), and [Avantis](/ai-agents/plugins/avantis) plugins that follow the same shape — this page shows how to write your own. ## When you need one -Write a plugin when your protocol either has an HTTP "tx-builder" that returns unsigned calldata, or exposes its own MCP server. If it has neither, you can still write one — point your assistant at any JSON-RPC node and have it encode the call directly. +Write a plugin when your protocol either has an HTTP "tx-builder" that returns unsigned calldata, or exposes its own MCP server. If it has neither, you can still use SDKs to encode the call directly, but it might not be useful for Claude and ChatGPT consumer apps. ## Anatomy of a plugin @@ -20,6 +20,9 @@ Every plugin file contains four sections: Document the GET endpoints that return state — balances, positions, market data — and the units they use. + + POST endpoints are not supported in Claude and ChatGPT consumer apps. + Document the endpoints (or MCP tools) that return unsigned calldata. State the exact response shape so the assistant knows which fields map to `to`, `value`, and `data`. @@ -30,7 +33,8 @@ Every plugin file contains four sections: -Custom plugin hostnames are not in the Base MCP `web_request` allowlist — only the native plugins are. When `web_request` rejects your domain, construct the prepare endpoint as a GET URL with all parameters in the query string, then either fetch it through whatever capability your harness exposes, or ask the user to paste the response into the chat. Once you have the JSON, the rest of the flow is identical. +Native plugins have access to the `web_request` tool from Base MCP, which allows them to make GET and POST requests to any hostname. +Custom plugins do not have access to the `web_request` tool, so they must use GET endpoints to be compatible with Claude and ChatGPT consumer apps. ## How it works @@ -175,21 +179,6 @@ The contract between your prepare endpoint and Base MCP is exactly this object: `chainId` is hex (`0x2105` for Base mainnet, `0x14a34` for Base Sepolia). `value` defaults to `0x0` if omitted. The assistant calls `send_calls` once with the full batch — the user approves once, and all calls execute atomically. -## Working example: a simple ERC-20 transfer plugin - -A minimal plugin that wraps an ERC-20 `transfer(address,uint256)` call. The prepare step is encoding the calldata; there's no external API. - -```text -1. get_wallets -> from -2. Encode transfer(to, amount): - 0xa9059cbb - + to padded to 32 bytes - + amount padded to 32 bytes -3. send_calls(chainId=0x2105, calls=[{ to: , value: "0x0", data: }]) -``` - -In your plugin spec, document the token addresses, the encoding rule, and the `send_calls` mapping. The assistant does the encoding inline. - ## Patterns to copy | Pattern | When to use | Example | @@ -198,15 +187,6 @@ In your plugin spec, document the token addresses, the encoding rule, and the `s | Ordered batch | Approval + action must be atomic | [Moonwell](/ai-agents/plugins/moonwell) | | Sibling MCP server | Protocol already runs an MCP server with `prepare_*` tools | [Morpho](/ai-agents/plugins/morpho) | | Multi-endpoint flow | Quote, approve, swap as separate calls | [Uniswap](/ai-agents/plugins/uniswap) | - -## Rules to follow - -- **Never sign or submit on behalf of the user.** Generating calldata and `send_calls` approval links is safe; the user must approve any real transaction. -- **Validate before preparing.** Tx-builders can encode calldata for invalid state (non-existent positions, insufficient balance) without erroring. Read state first. -- **Document units.** Spell out whether amounts are human decimals or base units. Mismatched units are the most common failure mode. -- **Keep approval before action.** When batching, the approval call must come first. -- **Don't combine chains in one batch.** `send_calls` executes on a single chain. - ## Related diff --git a/docs/ai-agents/plugins/moonwell.mdx b/docs/ai-agents/plugins/moonwell.mdx index 2539bd4aa..f5835ee27 100644 --- a/docs/ai-agents/plugins/moonwell.mdx +++ b/docs/ai-agents/plugins/moonwell.mdx @@ -148,7 +148,7 @@ Repay all my Moonwell USDC debt Full guide to `send_calls` and batching protocol interactions. - - Full Moonwell protocol documentation. + + Full Moonwell Agents documentation. diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index dbf5d25ca..f5d154475 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -134,10 +134,17 @@ import { AuthApprovalDemo } from "/snippets/AuthApprovalDemo.jsx" Download for Claude - 1. Click the button above to download `base-mcp.zip` - 2. In Claude Desktop or Claude.ai, open [**Customize → Skills**](https://claude.ai/customize/skills) - 3. Click **Upload skill** and select the downloaded `base-mcp.zip` - 4. Toggle the skill on + Click the button above to download `base-mcp.zip`, then pick one: + + **Option 1: Drop the zip into a conversation** + + Attach the downloaded `base-mcp.zip` to a new Claude conversation and ask Claude to read the skill and onboard you. Quickest way to try it without changing any settings. + + **Option 2: Install as a persistent skill** + + 1. In Claude Desktop or Claude.ai, open [**Customize → Skills**](https://claude.ai/customize/skills) + 2. Click **Upload skill** and select the downloaded `base-mcp.zip` + 3. Toggle the skill on Claude activates the skill automatically when relevant to your prompt. See [Use skills in Claude](https://support.claude.com/en/articles/12512180-use-skills-in-claude) for details. diff --git a/docs/docs.json b/docs/docs.json index 91318a4e9..a9420a34e 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -690,7 +690,8 @@ "ai-agents/guides/swap-tokens", "ai-agents/guides/view-history", "ai-agents/guides/sign-messages", - "ai-agents/guides/batch-calls" + "ai-agents/guides/batch-calls", + "ai-agents/guides/agent-builder-codes" ] }, { From ed85178750b9dda2b59c4625ab2d2042fd7ecb41 Mon Sep 17 00:00:00 2001 From: Youssef Date: Wed, 20 May 2026 17:00:54 +0100 Subject: [PATCH 27/36] remove builder codes guide --- docs/docs.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/docs.json b/docs/docs.json index a9420a34e..91318a4e9 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -690,8 +690,7 @@ "ai-agents/guides/swap-tokens", "ai-agents/guides/view-history", "ai-agents/guides/sign-messages", - "ai-agents/guides/batch-calls", - "ai-agents/guides/agent-builder-codes" + "ai-agents/guides/batch-calls" ] }, { From bfd47d935af87d15bf08b606a8baccfe3bd9b626 Mon Sep 17 00:00:00 2001 From: Youssef Date: Thu, 21 May 2026 01:55:35 +0100 Subject: [PATCH 28/36] update plugins --- docs/ai-agents/guides/batch-calls.mdx | 8 +- docs/ai-agents/guides/check-balance.mdx | 2 +- docs/ai-agents/guides/send-tokens.mdx | 2 +- docs/ai-agents/guides/sign-messages.mdx | 4 +- docs/ai-agents/guides/view-history.mdx | 2 +- docs/ai-agents/index.mdx | 6 +- docs/ai-agents/plugins/avantis.mdx | 121 -------------- .../{custom-plugin.mdx => custom-plugins.mdx} | 16 +- docs/ai-agents/plugins/index.mdx | 102 ++++++++++++ docs/ai-agents/plugins/moonwell.mdx | 154 ------------------ docs/ai-agents/plugins/morpho.mdx | 136 ---------------- docs/ai-agents/plugins/native-plugins.mdx | 68 ++++++++ docs/ai-agents/plugins/uniswap.mdx | 151 ----------------- docs/ai-agents/quickstart.mdx | 2 +- docs/docs.json | 10 +- docs/snippets/WalletSetupDemo.jsx | 19 +++ 16 files changed, 214 insertions(+), 589 deletions(-) delete mode 100644 docs/ai-agents/plugins/avantis.mdx rename docs/ai-agents/plugins/{custom-plugin.mdx => custom-plugins.mdx} (88%) create mode 100644 docs/ai-agents/plugins/index.mdx delete mode 100644 docs/ai-agents/plugins/moonwell.mdx delete mode 100644 docs/ai-agents/plugins/morpho.mdx create mode 100644 docs/ai-agents/plugins/native-plugins.mdx delete mode 100644 docs/ai-agents/plugins/uniswap.mdx diff --git a/docs/ai-agents/guides/batch-calls.mdx b/docs/ai-agents/guides/batch-calls.mdx index 7febccc87..bc0b692cc 100644 --- a/docs/ai-agents/guides/batch-calls.mdx +++ b/docs/ai-agents/guides/batch-calls.mdx @@ -12,11 +12,11 @@ import { AcceptingPaymentsDemo } from "/snippets/AcceptingPaymentsDemo.jsx" `send_calls` submits a batch of EIP-5792 contract calls to your Base Account in a single approval. Use it for DeFi interactions, multi-step operations, and NFT mints that go beyond simple send or swap. -The most common use case: protocol plugins like [Moonwell](/ai-agents/plugins/moonwell) prepare a `calls` array (including token approvals and deposits), and you pass it directly to `send_calls` — everything executes atomically in one approval. Moonwell works entirely via `web_request`, with no additional MCP server required. +The most common use case: [protocol plugins](/ai-agents/plugins/native-plugins) like Moonwell prepare a `calls` array (including token approvals and deposits), and you pass it directly to `send_calls` — everything executes atomically in one approval. Moonwell works entirely via `web_request`, with no additional MCP server required. ## What you can ask -With the [Moonwell plugin](/ai-agents/plugins/moonwell): +With the [Moonwell plugin](/ai-agents/plugins/native-plugins): ```text Find the best USDC market on Base and supply 100 USDC @@ -57,8 +57,8 @@ Repay all my Moonwell debt ## Related guides - - Full Moonwell orchestration pattern — query, prepare, execute. + + Morpho, Moonwell, Uniswap, and Avantis — full orchestration patterns in the skill repo. Sign individual messages and typed data. diff --git a/docs/ai-agents/guides/check-balance.mdx b/docs/ai-agents/guides/check-balance.mdx index 92caeca2a..4e6bd53a4 100644 --- a/docs/ai-agents/guides/check-balance.mdx +++ b/docs/ai-agents/guides/check-balance.mdx @@ -28,7 +28,7 @@ What tokens do I have in my wallet? ## How it works -**`get_wallets`** — lists all wallets in your wallet group (your Base Account plus any agent wallets). Shows which wallets are active in the current session (`inSession: true`). +**`get_wallets`** — lists all wallets in your wallet group (your Base Account plus any agent wallets). **`get_portfolio`** — returns portfolio value and per-asset breakdown for your connected wallet. diff --git a/docs/ai-agents/guides/send-tokens.mdx b/docs/ai-agents/guides/send-tokens.mdx index cc7e971aa..3f1e30a0e 100644 --- a/docs/ai-agents/guides/send-tokens.mdx +++ b/docs/ai-agents/guides/send-tokens.mdx @@ -35,7 +35,7 @@ The `send` tool constructs a transaction from your Base Account and requires you | `recipient` | Yes | Address, ENS name, basename (e.g. `alice.base.eth`), cb.id name, or username | | `amount` | Yes | Human-readable decimal (e.g. `"10.5"`) | | `asset` | Yes | Token symbol (`ETH`, `USDC`) or ERC-20 contract address | -| `chain` | Yes | `base` or `base-sepolia` | +| `chain` | Yes | Network to send on (e.g. `base`, `arbitrum`, `optimism`, `ethereum`) | | `decimals` | When using contract address | Required when `asset` is a contract address | diff --git a/docs/ai-agents/guides/sign-messages.mdx b/docs/ai-agents/guides/sign-messages.mdx index 31a09caf3..e0d990b36 100644 --- a/docs/ai-agents/guides/sign-messages.mdx +++ b/docs/ai-agents/guides/sign-messages.mdx @@ -54,7 +54,7 @@ Signing is usually invoked by protocols or integrations, not directly prompted b Batch multiple contract interactions into one approval. - - Example of signing-in-the-flow with a DeFi protocol. + + Morpho, Moonwell, Uniswap, and Avantis — signing in the flow with DeFi protocols. diff --git a/docs/ai-agents/guides/view-history.mdx b/docs/ai-agents/guides/view-history.mdx index b5b3bd8fe..5452051a6 100644 --- a/docs/ai-agents/guides/view-history.mdx +++ b/docs/ai-agents/guides/view-history.mdx @@ -33,7 +33,7 @@ Check the transaction history for 0x1234...abcd | Parameter | What it does | |-----------|-------------| | `address` | Address to query — defaults to your Base Account | -| `chain` | `base` or `ethereum` — defaults to `base` | +| `chain` | Network to query (e.g. `base`, `arbitrum`, `ethereum`) — defaults to `base` | | `asset` | Filter to a specific token (e.g. `USDC`, `ETH`) | | `limit` | Number of transactions per page (1–200, default 50) | | `cursor` | Pagination cursor from the previous response's `nextCursor` | diff --git a/docs/ai-agents/index.mdx b/docs/ai-agents/index.mdx index cd2b419a3..ba3f9be5a 100644 --- a/docs/ai-agents/index.mdx +++ b/docs/ai-agents/index.mdx @@ -6,7 +6,7 @@ keywords: ["Base MCP", "AI agent wallet", "mcp.base.org", "AI assistant wallet", import { WalletSetupDemo } from "/snippets/WalletSetupDemo.jsx" -Base MCP gives your AI assistant direct access to your [Base Account](https://base.org/account) — a smart wallet on Base. Connect once and your assistant can check balances, send funds, swap tokens, and sign messages. Every transaction requires your approval. +Base MCP gives your AI assistant direct access to your [Base Account](https://base.org/account) — a smart wallet. Connect once and your assistant can check balances, send funds, swap tokens, sign messages, and execute contract calls across multiple networks. Every transaction requires your approval. ## Demo @@ -60,8 +60,8 @@ sequenceDiagram Step-by-step guides for sending, swapping, checking balance, and more. - - Extend with protocol plugins like Moonwell for lending and vaults. + + How the Base MCP skill works and how plugins like Morpho, Moonwell, Uniswap, and Avantis extend it. Build your own plugin that produces unsigned calldata and executes through Base MCP's send_calls. diff --git a/docs/ai-agents/plugins/avantis.mdx b/docs/ai-agents/plugins/avantis.mdx deleted file mode 100644 index ec027c7dd..000000000 --- a/docs/ai-agents/plugins/avantis.mdx +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: "Avantis" -description: "Add perpetual futures trading to your AI assistant on Base using Avantis and Base Account — no additional MCP server required" -keywords: ["Avantis perpetuals AI Base", "perp trading agent Base", "Avantis tx-builder", "DeFi futures agent Base", "Avantis MCP"] ---- - -import { TradeExecutionDemo } from "/snippets/TradeExecutionDemo.jsx" - -[Avantis](https://avantisfi.com) is a perpetual futures DEX on Base mainnet. Your assistant uses `web_request` to fetch unsigned calldata from the Avantis tx-builder, then executes via Base MCP's `send_calls` — no additional MCP server required. - -## Demo - - - -## How it works - -Avantis prepares the trade calldata. Your Base Account handles signing. - -```mermaid -sequenceDiagram - participant User - participant AI as AI Assistant - participant AV as Avantis API - participant BA as Base MCP - - User->>AI: "Open a 10x long BTC/USD with 100 USDC" - AI->>AV: GET /v2/trading (validate pair, leverage) - AV-->>AI: pair config - AI->>AV: GET /user-data?trader=
- AV-->>AI: existing positions - AI->>AV: GET /token/approve?trader=
&amountUsdc=100 - AV-->>AI: approve calldata - AI->>AV: GET /trade/open?pair=BTC/USD&side=long&leverage=10&collateralUsdc=100 - AV-->>AI: trade calldata - AI->>BA: send_calls(calls=[approve, open]) - BA-->>AI: { approvalUrl, requestId } - AI-->>User: "Please approve: [link]" -``` - - -The following domains must be in the Base MCP `web_request` allowlist: `tx-builder.avantisfi.com`, `data.avantisfi.com`, `core.avantisfi.com`, and `api.avantisfi.com`. No API key is required. - - -## API services - -| Service | Base URL | Purpose | -|---------|----------|---------| -| tx-builder | `https://tx-builder.avantisfi.com` | Unsigned calldata for all trade actions | -| data | `https://data.avantisfi.com/v2/trading` | Pair configs, leverage rules, open interest | -| core | `https://core.avantisfi.com` | Live positions and limit orders | -| history | `https://api.avantisfi.com` | Trade history, PnL, referral stats | - -## Example prompts - -**Open a long position:** -```text -Open a 10x long BTC/USD position with 100 USDC on Avantis -``` - -**Check positions:** -```text -Show my open Avantis positions on Base -``` - -**Close a position:** -```text -Close my BTC/USD long on Avantis -``` - -**Set take profit and stop loss:** -```text -Set take profit at $120,000 and stop loss at $80,000 on my BTC/USD position -``` - -## Orchestration pattern - - - - Call `GET https://data.avantisfi.com/v2/trading` to confirm the pair is listed, leverage is within range, and the position size meets the minimum notional (`collateralUsdc × leverage ≥ pairMinLevPosUSDC`). - - - Call `GET https://core.avantisfi.com/user-data?trader=
` to see live positions and limit orders. Use the real `index` values from this response for any management actions. - - - Call `GET https://tx-builder.avantisfi.com/token/approve?trader=
&amountUsdc=` to get approval calldata. - - - Call the relevant tx-builder endpoint for the desired action. - - - Batch approval and trade calls into a single `send_calls` call. You'll get an `approvalUrl`. - - - -## Trade operations - -All tx-builder responses use the shape `{ ok, data: { to, value, data, chainId } }`. Map `data.to`, `data.value`, and `data.data` to a call object in `send_calls`. - -| Action | Endpoint | -|--------|---------| -| Open position | `GET /trade/open?trader=&pair=BTC/USD&side=long&orderType=market&collateralUsdc=100&leverage=10` | -| Close position | `GET /trade/close?trader=&pairIndex=&tradeIndex=` | -| Cancel limit order | `GET /trade/cancel?trader=&pairIndex=&tradeIndex=` | -| Deposit/withdraw margin | `GET /margin/update?trader=&pairIndex=&tradeIndex=&action=deposit&collateralUsdc=10` | -| Set TP/SL | `GET /tpsl/update?trader=&pairIndex=&tradeIndex=&takeProfit=120000&stopLoss=80000` | -| Approve USDC | `GET /token/approve?trader=&amountUsdc=100` | - - -Always read `core /user-data` before any management action (close, cancel, margin, TP/SL). The tx-builder can encode calldata for a non-existent index without error — verify the position exists first. - - -## Related - - - - Full guide to `send_calls` and batching protocol interactions. - - - Full Avantis protocol documentation. - - diff --git a/docs/ai-agents/plugins/custom-plugin.mdx b/docs/ai-agents/plugins/custom-plugins.mdx similarity index 88% rename from docs/ai-agents/plugins/custom-plugin.mdx rename to docs/ai-agents/plugins/custom-plugins.mdx index 8bd024c2a..a2cd83120 100644 --- a/docs/ai-agents/plugins/custom-plugin.mdx +++ b/docs/ai-agents/plugins/custom-plugins.mdx @@ -1,10 +1,10 @@ --- -title: "Build a Custom Plugin" +title: "Custom Plugins" description: "Build your own plugin that produces unsigned calldata and executes through Base MCP's send_calls" keywords: ["custom Base MCP plugin", "AI agent plugin Base", "send_calls custom protocol", "Base MCP web_request plugin", "build MCP plugin"] --- -A plugin is a markdown spec that teaches your assistant how to call an external API (or another MCP server), translate the response into a `calls` array, and execute it through Base MCP's `send_calls`. Examples include [Moonwell](/ai-agents/plugins/moonwell), [Morpho](/ai-agents/plugins/morpho), [Uniswap](/ai-agents/plugins/uniswap), and [Avantis](/ai-agents/plugins/avantis) plugins that follow the same shape — this page shows how to write your own. +A plugin is a markdown spec that teaches your assistant how to call an external API (or another MCP server), translate the response into a `calls` array, and execute it through Base MCP's `send_calls`. The [native plugins](/ai-agents/plugins/native-plugins) — Morpho, Moonwell, Uniswap, and Avantis — all follow the same shape. This page shows how to write your own. ## When you need one @@ -183,17 +183,17 @@ The contract between your prepare endpoint and Base MCP is exactly this object: | Pattern | When to use | Example | |---------|-------------|---------| -| Single-call envelope | One action, one tx | [Avantis](/ai-agents/plugins/avantis) | -| Ordered batch | Approval + action must be atomic | [Moonwell](/ai-agents/plugins/moonwell) | -| Sibling MCP server | Protocol already runs an MCP server with `prepare_*` tools | [Morpho](/ai-agents/plugins/morpho) | -| Multi-endpoint flow | Quote, approve, swap as separate calls | [Uniswap](/ai-agents/plugins/uniswap) | +| Single-call envelope | One action, one tx | [Avantis](https://github.com/base/skills/blob/main/skills/base-mcp/plugins/avantis.md) | +| Ordered batch | Approval + action must be atomic | [Moonwell](https://github.com/base/skills/blob/main/skills/base-mcp/plugins/moonwell.md) | +| Sibling MCP server | Protocol already runs an MCP server with `prepare_*` tools | [Morpho](https://github.com/base/skills/blob/main/skills/base-mcp/plugins/morpho.md) | +| Multi-endpoint flow | Quote, approve, swap as separate calls | [Uniswap](https://github.com/base/skills/blob/main/skills/base-mcp/plugins/uniswap.md) | ## Related Full guide to `send_calls` and batching. - - Reference implementation using the ordered-batch pattern. + + Reference implementations for the ordered-batch, sibling-MCP, and multi-endpoint patterns. diff --git a/docs/ai-agents/plugins/index.mdx b/docs/ai-agents/plugins/index.mdx new file mode 100644 index 000000000..ad98b963e --- /dev/null +++ b/docs/ai-agents/plugins/index.mdx @@ -0,0 +1,102 @@ +--- +title: "Overview" +description: "How the Base MCP Skill works and how plugins extend it" +keywords: ["Base MCP skill", "Anthropic Skills", "SKILL.md", "Base MCP plugins", "send_calls plugin pattern"] +--- + + +This page describes how the Base MCP Skill and Plugins work under the hood. If you just want to install it in Claude Desktop, ChatGPT, Cursor, or Claude Code, head to the [Quickstart](/ai-agents/quickstart). + + +## Why a skill on top of the MCP server + +The MCP server exposes capabilities. Without context, models misuse them — calling write tools without warning the user, skipping approval, inventing parameters, or failing to detect that the server isn't connected at all. The skill closes that gap. Specifically, `SKILL.md` adds: + +- **Detection and onboarding** — every session starts with `get_wallets` so the assistant knows whether the MCP is connected and which Base account it's working with. +- **Approval mode** — write tools (`send`, `swap`, `sign`, `send_calls`) return `{ approvalUrl, requestId }`. The skill tells the model to present the link, wait, then poll `get_request_status` — never to claim success before confirmation. +- **Tone rules** — load-bearing language conventions (e.g. "onchain", never "web3") and a beginner/sophisticated detection heuristic so responses match the user. +- **A plugin contract** — a documented prepare → `send_calls` pattern that lets external protocols extend the skill without modifying the MCP server. + +## How SKILL.md is loaded + +Skills use progressive disclosure. The model loads `SKILL.md` at session start (cheap — ~100 lines) and reads `references/*.md` and `plugins/*.md` only when a relevant task arises. + +The shape of the Base MCP skill: + + + + + + + + + + + + + + + + + + + + +`SKILL.md` itself defines the session flow: **Detection → Tone → Onboarding → Tools table → Plugins table**. When the user asks to swap tokens, the model pulls in `references/tools.md`. When they ask about a Morpho vault, the model pulls in `plugins/morpho.md`. Nothing else is in context. + +Read the canonical file at [`skills/base-mcp/SKILL.md`](https://github.com/base/skills/blob/main/skills/base-mcp/SKILL.md). + +## How plugins extend the skill + +A plugin is a markdown spec — one file in `plugins/` — that teaches the assistant how to drive an external protocol through `send_calls`. The contract is the same whether the protocol exposes an HTTP "tx-builder" or its own sibling MCP server: + +```mermaid +sequenceDiagram + participant User + participant AI as AI Assistant + participant Protocol as Protocol API / MCP + participant BA as Base MCP + + User->>AI: "Do on " + AI->>Protocol: read state (balances, markets, positions) + Protocol-->>AI: state + AI->>Protocol: prepare (unsigned calldata) + Protocol-->>AI: { to, value, data, chainId } + AI->>BA: send_calls(chainId, calls=[...]) + BA-->>AI: { approvalUrl, requestId } + AI-->>User: "Please approve: [link]" + User-->>AI: approved + AI->>BA: get_request_status(requestId) + BA-->>AI: confirmed +``` + +Every plugin file follows the same four-section shape: + + + + A `STOP` notice forcing the assistant to complete Base MCP detection and onboarding before touching the plugin's tools. + + + The GET endpoints (or read tools) that return state — balances, positions, market data. + + + The endpoints (or `prepare_*` tools) that return unsigned calldata, with the exact response shape so the model knows which fields map to `to`, `value`, and `data`. + + + How to turn the prepare response into the `calls` array passed to Base MCP's `send_calls`. + + + +Base MCP signs and submits. The protocol never touches keys. + +## Native vs custom plugins + + + + Morpho, Moonwell, Uniswap, Avantis — authored by the Base team and shipped with the skill. + + + Write your own markdown spec for any protocol with an HTTP tx-builder or MCP server. + + + diff --git a/docs/ai-agents/plugins/moonwell.mdx b/docs/ai-agents/plugins/moonwell.mdx deleted file mode 100644 index f5835ee27..000000000 --- a/docs/ai-agents/plugins/moonwell.mdx +++ /dev/null @@ -1,154 +0,0 @@ ---- -title: "Moonwell" -description: "Add Moonwell lending operations to your AI assistant using web_request and Base Account — no additional MCP server required" -keywords: ["Moonwell Base lending AI", "Moonwell supply borrow agent", "Compound v2 Base AI", "DeFi lending agent Base", "Moonwell MCP"] ---- - -import { AgentPaymentDemo } from "/snippets/AgentPaymentDemo.jsx" - -[Moonwell](https://moonwell.fi) is a Compound v2 lending protocol on Base and Optimism. Your assistant uses `web_request` to call the Moonwell HTTP API and prepare unsigned calldata, then executes via Base MCP's `send_calls` — no additional MCP server required. - -## Demo - - - -## How it works - -Moonwell handles the protocol layer. Your Base Account handles signing. - -```mermaid -sequenceDiagram - participant User - participant AI as AI Assistant - participant Moonwell as Moonwell API - participant BA as Base MCP - - User->>AI: "Supply 100 USDC to the best market" - AI->>Moonwell: GET /v1/yield?chain=base&sort=apy - Moonwell-->>AI: market list with APYs - AI->>Moonwell: GET /v1/prepare/supply?chain=base&asset=USDC&amountDecimal=100&from=
- Moonwell-->>AI: { transactions: [approve, enter-market, supply] } - AI->>BA: send_calls(0x2105, calls from transactions[]) - BA-->>AI: { approvalUrl, requestId } - AI-->>User: "Please approve: [link]" - User-->>AI: approved - AI->>BA: get_request_status(requestId) - BA-->>AI: confirmed - AI-->>User: "100 USDC supplied" -``` - - -`api.moonwell.fi` must be in the Base MCP `web_request` allowlist. If requests are rejected, inform the user that this hostname is not yet whitelisted on this MCP instance. - - -## Supported chains - -Base (8453) and Optimism (10). - -## Read endpoints - -```text -GET https://api.moonwell.fi/v1/markets?chain=base -GET https://api.moonwell.fi/v1/markets/USDC?chain=base -GET https://api.moonwell.fi/v1/yield?chain=base&sort=apy&min-tvl=1000000&limit=5 -GET https://api.moonwell.fi/v1/positions/
?chain=base&active=true -GET https://api.moonwell.fi/v1/health/
?chain=base -GET https://api.moonwell.fi/v1/rewards/
?chain=base -GET https://api.moonwell.fi/v1/token-balance/
?chain=base&asset=USDC -``` - -Market reads are edge-cached for 30 seconds. Position, health, and balance reads are never cached. - -## Prepare endpoints - -All write operations go through prepare endpoints that return ordered, unsigned transactions. - -```text -GET https://api.moonwell.fi/v1/prepare/supply?chain=base&asset=USDC&amountDecimal=100&from=
-GET https://api.moonwell.fi/v1/prepare/withdraw?chain=base&asset=USDC&amountDecimal=100&from=
-GET https://api.moonwell.fi/v1/prepare/borrow?chain=base&asset=USDC&amountDecimal=50&from=
-GET https://api.moonwell.fi/v1/prepare/repay?chain=base&asset=USDC&amountDecimal=50&from=
-``` - -### Response → send_calls mapping - -```json -{ - "data": { - "transactions": [ - { "step": "approve", "to": "0x...", "data": "0x...", "value": "0x0", "chainId": 8453 }, - { "step": "enter-market", "to": "0x...", "data": "0x...", "value": "0x0", "chainId": 8453 }, - { "step": "moonwell-supply", "to": "0x...", "data": "0x...", "value": "0x0", "chainId": 8453 } - ] - } -} -``` - -Pass all items as the `calls` array to `send_calls`, using `0x2105` as `chainId` for Base mainnet. - -## Example prompts - -**Supply USDC:** -```text -Find the best USDC market on Base by APY and supply 100 USDC -``` - -**Borrow against collateral:** -```text -Borrow 500 USDC against my collateral on Moonwell -``` - -**Check positions:** -```text -Show all my active Moonwell positions on Base -``` - -**Check health:** -```text -What's my Moonwell health factor? -``` - -**Repay:** -```text -Repay all my Moonwell USDC debt -``` - -## Orchestration pattern - - - - Use `/v1/yield` to find the best market by APY. Use `/v1/positions/
?active=true` to see existing positions. - - - Call `/v1/health/
` before borrowing. Proceed only when the health factor is above 1.5. - - - Call the prepare endpoint. Moonwell returns an ordered `transactions[]` array including any required approvals. - - - Pass all transactions as the `calls` array to `send_calls`. You'll get an `approvalUrl`. - - - Open the `approvalUrl`, approve the transaction, then your assistant polls `get_request_status`. - - - -## Health factor guide - -| Value | Status | -|-------|--------| -| `> 1.5` | Healthy | -| `1.1 – 1.5` | Caution | -| `< 1.1` | Liquidation risk | -| `null` | No borrows | - -## Related - - - - Full guide to `send_calls` and batching protocol interactions. - - - Full Moonwell Agents documentation. - - diff --git a/docs/ai-agents/plugins/morpho.mdx b/docs/ai-agents/plugins/morpho.mdx deleted file mode 100644 index 510e6da39..000000000 --- a/docs/ai-agents/plugins/morpho.mdx +++ /dev/null @@ -1,136 +0,0 @@ ---- -title: "Morpho" -description: "Add Morpho lending and vault operations to your AI assistant via the Morpho MCP, executed through your Base Account" -keywords: ["Morpho MCP", "Base lending AI", "Morpho vault agent", "mcp.morpho.org", "AI lending agent Base"] ---- - -import { AcceptingPaymentsDemo } from "/snippets/AcceptingPaymentsDemo.jsx" - -[Morpho](https://morpho.org) is a lending protocol on Base. The Morpho MCP server gives your assistant tools to query vaults, check markets, and prepare lending operations — which are then signed and sent through Base MCP. - -## Demo - - - -## How it works - -Morpho handles the protocol layer. Your Base Account handles signing. - -```mermaid -sequenceDiagram - participant User - participant AI as AI Assistant - participant Morpho as Morpho MCP - participant BA as Base MCP - - User->>AI: "Deposit 100 USDC into the best vault" - AI->>Morpho: morpho_query_vaults(asset=USDC, sortBy=APY) - Morpho-->>AI: vault list with APYs - AI->>Morpho: morpho_prepare_deposit(vaultAddress, 100 USDC) - Morpho-->>AI: { calls, chainId } (simulated, unsigned) - AI->>BA: send_calls(chainId, calls) - BA-->>AI: { approvalUrl, requestId } - AI-->>User: "Please approve: [link]" - User-->>AI: approved - AI->>BA: get_request_status(requestId) - BA-->>AI: confirmed - AI-->>User: "100 USDC deposited" -``` - - -Morpho's `prepare_*` tools simulate the transaction before returning. Review the simulation output before approving — it shows expected state changes, health factors, and any warnings. - - -## Morpho tools - -17 tools across read, write (prepare), and simulate. - -### Read - -| Tool | What it does | -|------|-------------| -| `morpho_health_check` | Check server connectivity | -| `morpho_get_supported_chains` | List supported chains | -| `morpho_query_vaults` | List vaults with filtering and sorting | -| `morpho_get_vault` | Details for a specific vault | -| `morpho_query_markets` | List markets with filtering | -| `morpho_get_market` | Details for a specific market | -| `morpho_get_positions` | All positions for an address (vaults + markets) | -| `morpho_get_token_balance` | Token balance and approval state | - -### Prepare (write via `send_calls`) - -These tools return unsigned call data. Pass the result to Base MCP's `send_calls` to execute. - -| Tool | What it does | -|------|-------------| -| `morpho_prepare_deposit` | Prepare vault deposit with token approvals | -| `morpho_prepare_withdraw` | Prepare vault withdrawal (supports max) | -| `morpho_prepare_supply` | Prepare market supply with approvals | -| `morpho_prepare_borrow` | Prepare market borrow with health check | -| `morpho_prepare_repay` | Prepare market repay (supports max) | -| `morpho_prepare_supply_collateral` | Supply collateral to a market | -| `morpho_prepare_withdraw_collateral` | Withdraw collateral with health check | - -### Simulate - -| Tool | What it does | -|------|-------------| -| `morpho_simulate_transactions` | Simulate transactions with post-state analysis | - -## Example prompts - -**Deposit into a vault:** -```text -Find the best USDC vault on Base by APY and deposit 100 USDC -``` - -**Check positions:** -```text -Show all my Morpho positions on Base -``` - -**Borrow against collateral:** -```text -Supply 1 ETH as collateral on Morpho and borrow 2000 USDC -``` - -**Check health:** -```text -What's my Morpho borrow health factor? -``` - -**Withdraw:** -```text -Withdraw all my USDC from Morpho vaults -``` - -## Orchestration pattern - -Every Morpho write operation follows the same pattern: - - - - Use a read tool to find the right vault or market: `morpho_query_vaults`, `morpho_get_market`, etc. - - - Call a `prepare_*` tool. Morpho simulates the operation and returns `{ calls, chainId }`. - - - Pass `calls` and `chainId` to Base MCP's `send_calls`. You'll get an `approvalUrl`. - - - Open the `approvalUrl`, approve the transaction, then your assistant polls `get_request_status`. - - - -## Related - - - - Full guide to `send_calls` and batching protocol interactions. - - - Full Morpho MCP documentation and prompt library. - - diff --git a/docs/ai-agents/plugins/native-plugins.mdx b/docs/ai-agents/plugins/native-plugins.mdx new file mode 100644 index 000000000..c0bf2d177 --- /dev/null +++ b/docs/ai-agents/plugins/native-plugins.mdx @@ -0,0 +1,68 @@ +--- +title: "Native Plugins" +description: "Plugins authored by the Base team that ship with the Base MCP skill" +keywords: ["Base MCP plugins", "Morpho plugin", "Moonwell plugin", "Uniswap plugin", "Avantis plugin"] +--- + +Four plugins ship in the Base MCP skill — Morpho, Moonwell, Uniswap, and Avantis. They're authored by the Base team and live alongside `SKILL.md` in [`github.com/base/skills`](https://github.com/base/skills/tree/main/skills/base-mcp/plugins). The assistant loads each spec on demand when a relevant request comes in. + +All four follow the same prepare → `send_calls` contract described in the [Overview](/ai-agents/plugins). The plugin spec is the single source of truth; the cards below are pointers, not duplicates. + +## The plugins + + + + Lending and vaults on Base. Uses Morpho's sibling MCP server at `mcp.morpho.org` for `prepare_*` tools that return simulated, unsigned calldata. 17 tools across read, write, and simulate. + + + Lending on Base and Optimism. Uses `web_request` against `api.moonwell.fi` to fetch ordered transactions — approve, enter-market, action — executed atomically through `send_calls`. + + + Token swaps and V2/V3/V4 LP positions on Base. Uses `web_request` against the Uniswap trade API for quote, approval, and swap calldata. + + + Perpetual futures on Base. Uses `web_request` against the Avantis tx-builder for open, close, update, and limit-order calldata. + + + +## Using a native plugin + + + + Connect `mcp.base.org` and load the skill in your client. See the [Quickstart](/ai-agents/quickstart) for Claude Desktop, ChatGPT, Cursor, and Claude Code. + + + Just describe what you want. The assistant pulls the relevant plugin spec into context automatically. + + ```text Morpho + Find the best USDC vault on Base by APY and deposit 100 USDC + ``` + + ```text Moonwell + Borrow 500 USDC against my collateral on Moonwell + ``` + + ```text Uniswap + Swap 100 USDC for ETH on Base + ``` + + ```text Avantis + Open a 10x long BTC/USD with 100 USDC collateral + ``` + + + The plugin returns unsigned calldata; Base MCP's `send_calls` wraps it into a single approval. Open the `approvalUrl` at `keys.coinbase.com`, approve, and the assistant polls `get_request_status` until confirmed. + + + + +Plugins that use `web_request` only reach protocols whose hostnames are on the Base MCP allowlist. The four native plugins above are already covered. To call a protocol that isn't, see [Build a custom plugin](/ai-agents/plugins/custom-plugin). + + +## Build your own + + + + Same prepare → `send_calls` pattern, written as a markdown spec for any protocol with an HTTP tx-builder or MCP server. + + diff --git a/docs/ai-agents/plugins/uniswap.mdx b/docs/ai-agents/plugins/uniswap.mdx deleted file mode 100644 index f8020897c..000000000 --- a/docs/ai-agents/plugins/uniswap.mdx +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: "Uniswap" -description: "Add token swaps and LP position management to your AI assistant on Base using the Uniswap API and Base Account — no additional MCP server required" -keywords: ["Uniswap swap AI Base", "Uniswap LP agent", "token swap agent Base", "Uniswap V4 Base AI", "DeFi swap agent Base"] ---- - -import { TradingQuickstartDemo } from "/snippets/TradingQuickstartDemo.jsx" - -[Uniswap](https://uniswap.org) on Base: token swaps using the proxy-approval flow and LP position management for V2, V3, and V4. Your assistant uses `web_request` to fetch unsigned calldata from the Uniswap API, then executes via Base MCP's `send_calls` — no additional MCP server required. - -## Demo - - - -## How it works - -Uniswap API prepares the swap or LP calldata. Your Base Account handles signing. - -```mermaid -sequenceDiagram - participant User - participant AI as AI Assistant - participant UNI as Uniswap API - participant BA as Base MCP - - User->>AI: "Swap 100 USDC for ETH on Base" - AI->>UNI: POST /check_approval (x-permit2-disabled: true) - UNI-->>AI: approval calldata (if needed) - AI->>UNI: POST /quote (x-permit2-disabled: true) - UNI-->>AI: best route - AI->>UNI: POST /swap (x-permit2-disabled: true) - UNI-->>AI: unsigned swap tx - AI->>BA: send_calls(calls=[approval, swap]) - BA-->>AI: { approvalUrl, requestId } - AI-->>User: "Please approve: [link]" -``` - - -`trade-api.gateway.uniswap.org` and `liquidity.api.uniswap.org` must be in the Base MCP `web_request` allowlist. - - -## Auth headers - -Include these headers on all requests: - -```json -{ - "Content-Type": "application/json", - "x-api-key": "NeoYO3V50_koJAipDEalYWbMO1XMaFPAQmpOm6_Npo0" -} -``` - -For the swap flow, also include `"x-permit2-disabled": "true"` on `/check_approval`, `/quote`, and `/swap`. - -## Example prompts - -**Swap tokens:** -```text -Swap 100 USDC for ETH on Base -``` - -**Create an LP position:** -```text -Create a V4 ETH/USDC LP position on Base with 0.1 ETH -``` - -**Add liquidity:** -```text -Add liquidity to my existing Uniswap V4 ETH/USDC position -``` - -**Collect fees:** -```text -Collect my Uniswap LP fees on Base -``` - -**Remove liquidity:** -```text -Remove 50% of my Uniswap V3 liquidity position -``` - -## Swap flow - -Base URL: `https://trade-api.gateway.uniswap.org/v1` - - - - `POST /check_approval` with `x-permit2-disabled: true`. If `approval` is non-null, include it in the `send_calls` batch. - - - `POST /quote` with `x-permit2-disabled: true`. Returns the best route. - - - `POST /swap` using the quote response as the body. Remove null `permitData`, `permitTransaction`, and `signature` fields before sending. - - - Batch approval (if present) and swap calldata into a single `send_calls` call. - - - -## LP flow - -Base URL: `https://liquidity.api.uniswap.org/lp` - - - - `POST /lp/pool_info` to find the pool reference. Required before creating V3/V4 positions. - - - `POST /lp/check_approval` with `lpTokens` array and the relevant action (`CREATE`, `INCREASE`, `DECREASE`). - - - Call `/lp/create`, `/lp/increase`, `/lp/decrease`, `/lp/claim_fees`, or `/lp/create_classic`. - - - Batch all approval transactions plus the operation transaction into a single `send_calls` call. - - - -## LP operations - -| Action | Endpoint | -|--------|---------| -| Create V3/V4 position | `POST /lp/create` | -| Create V2 position | `POST /lp/create_classic` | -| Add liquidity | `POST /lp/increase` | -| Remove liquidity | `POST /lp/decrease` | -| Collect fees | `POST /lp/claim_fees` | - -No approval step is needed for fee collection. - -## Key addresses on Base - -| Token | Address | -|-------|---------| -| Native ETH | `0x0000000000000000000000000000000000000000` | -| USDC | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | -| WETH | `0x4200000000000000000000000000000000000006` | - -Token amounts are in base units: USDC = 1e6 per token, ETH/WETH = 1e18 per token. - -## Related - - - - Full guide to `send_calls` and batching protocol interactions. - - - Full Uniswap protocol documentation. - - diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index f5d154475..2a466d15c 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -1,5 +1,5 @@ --- -title: "Quickstart" +title: "Get Started with Base MCP" description: "Connect Base MCP to your agent in under 2 minutes" keywords: ["Base MCP quickstart", "mcp.base.org setup", "Claude Desktop MCP", "ChatGPT MCP", "Claude Code MCP wallet", "Cursor MCP", "Codex MCP", "Hermes MCP"] --- diff --git a/docs/docs.json b/docs/docs.json index 91318a4e9..6e054eaac 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -694,13 +694,11 @@ ] }, { - "group": "Plugins [WIP]", + "group": "Skill & Plugins [WIP]", "pages": [ - "ai-agents/plugins/moonwell", - "ai-agents/plugins/morpho", - "ai-agents/plugins/uniswap", - "ai-agents/plugins/avantis", - "ai-agents/plugins/custom-plugin" + "ai-agents/plugins/index", + "ai-agents/plugins/native-plugins", + "ai-agents/plugins/custom-plugins" ] } ] diff --git a/docs/snippets/WalletSetupDemo.jsx b/docs/snippets/WalletSetupDemo.jsx index b022bc88a..25d9d8b8b 100644 --- a/docs/snippets/WalletSetupDemo.jsx +++ b/docs/snippets/WalletSetupDemo.jsx @@ -554,6 +554,25 @@ export const WalletSetupDemo = () => { { delay: 1100, type: "confirm", text: "Deposited 100 USDC into Steakhouse USDC · earning 8.42% APY" }, ], }, + { + prompt: "What chains are supported by Base MCP?", + events: [ + { delay: 380, type: "thinking" }, + { delay: 500, type: "text", text: "Base MCP supports 8 mainnets and 2 testnets:" }, + { delay: 200, type: "rows", rows: [ + { token: "Base", amount: "Mainnet", value: "" }, + { token: "Arbitrum", amount: "Mainnet", value: "" }, + { token: "Optimism", amount: "Mainnet", value: "" }, + { token: "Zora", amount: "Mainnet", value: "" }, + { token: "Polygon", amount: "Mainnet", value: "" }, + { token: "BNB Chain", amount: "Mainnet", value: "" }, + { token: "Avalanche", amount: "Mainnet", value: "" }, + { token: "Ethereum", amount: "Mainnet", value: "" }, + { token: "Base Sepolia", amount: "Testnet", value: "" }, + { token: "Sepolia", amount: "Testnet", value: "" }, + ]}, + ], + }, ]; const [activeIdx, setActiveIdx] = useState(null); From 40236ca7b9eb10f2e39f597d3b2fbdb1f3a914cc Mon Sep 17 00:00:00 2001 From: Montana Wong Date: Thu, 21 May 2026 09:52:16 -0400 Subject: [PATCH 29/36] clarify plugin signing flow and update prompts Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/ai-agents/plugins/index.mdx | 2 +- docs/ai-agents/plugins/native-plugins.mdx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/ai-agents/plugins/index.mdx b/docs/ai-agents/plugins/index.mdx index ad98b963e..c8fb71fcb 100644 --- a/docs/ai-agents/plugins/index.mdx +++ b/docs/ai-agents/plugins/index.mdx @@ -87,7 +87,7 @@ Every plugin file follows the same four-section shape: -Base MCP signs and submits. The protocol never touches keys. +Base MCP passes the calldata for the user to sign and submit. The protocol never touches private keys. ## Native vs custom plugins diff --git a/docs/ai-agents/plugins/native-plugins.mdx b/docs/ai-agents/plugins/native-plugins.mdx index c0bf2d177..628be9de0 100644 --- a/docs/ai-agents/plugins/native-plugins.mdx +++ b/docs/ai-agents/plugins/native-plugins.mdx @@ -29,7 +29,7 @@ All four follow the same prepare → `send_calls` contract described in the [Ove - Connect `mcp.base.org` and load the skill in your client. See the [Quickstart](/ai-agents/quickstart) for Claude Desktop, ChatGPT, Cursor, and Claude Code. + Connect `mcp.base.org` and load the skill in your client. See the [Quickstart](/ai-agents/quickstart) for Claude, Claude Desktop, ChatGPT, Cursor, and Claude Code. Just describe what you want. The assistant pulls the relevant plugin spec into context automatically. @@ -43,7 +43,7 @@ All four follow the same prepare → `send_calls` contract described in the [Ove ``` ```text Uniswap - Swap 100 USDC for ETH on Base + Create a ETH/USDC LP position on Uniswap ``` ```text Avantis @@ -51,7 +51,7 @@ All four follow the same prepare → `send_calls` contract described in the [Ove ``` - The plugin returns unsigned calldata; Base MCP's `send_calls` wraps it into a single approval. Open the `approvalUrl` at `keys.coinbase.com`, approve, and the assistant polls `get_request_status` until confirmed. + The plugin returns unsigned calldata; Base MCP's `send_calls` wraps it into a single approval. Open the `approvalUrl` at `keys.coinbase.com`, approve, and prompt the assistant again and it will poll `get_request_status` until confirmed. From ad087bb2b8dd0cdd1cba155f5b134150a1ca463c Mon Sep 17 00:00:00 2001 From: Montana Wong Date: Thu, 21 May 2026 10:20:11 -0400 Subject: [PATCH 30/36] move auth approval step into Claude and ChatGPT connector setup Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/ai-agents/quickstart.mdx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index 2a466d15c..068b49ffa 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -29,7 +29,9 @@ import { AuthApprovalDemo } from "/snippets/AuthApprovalDemo.jsx" - **Name**: `Base` - **Remote MCP server URL**: `https://mcp.base.org` 4. Click **Add** - + 5. Next hit **Connect**, you will be directed to `keys.coinbase.com` to connect your Base Account. Click **Allow** once to authorize: + + @@ -47,8 +49,7 @@ import { AuthApprovalDemo } from "/snippets/AuthApprovalDemo.jsx" - **Authentication**: `OAuth` 4. Check **I understand and want to continue** on the risk warning 5. Click **Create** - - ChatGPT will prompt you to authorize when you first use a wallet tool. + 6. You will be automatically redirected to `keys.coinbase.com` to connect your Base Account. Click **Allow** once to authorize. Run this in your terminal to add the server to the current project: @@ -204,11 +205,7 @@ import { AuthApprovalDemo } from "/snippets/AuthApprovalDemo.jsx" - The first time you call a wallet tool, your assistant opens an auth modal at `keys.coinbase.com` to connect your Base Account. Click **Allow** once to authorize: - - - - Then ask your assistant: + Ask your assistant: ```text Show me my wallets From 54cd50099583a78f9fc8f4e968fad9a3c0b4efe0 Mon Sep 17 00:00:00 2001 From: Youssef Date: Thu, 21 May 2026 16:01:54 +0100 Subject: [PATCH 31/36] update native plugins pages --- docs/ai-agents/plugins/native-plugins.mdx | 16 ++++---- docs/ai-agents/plugins/native/avantis.mdx | 43 +++++++++++++++++++ docs/ai-agents/plugins/native/moonwell.mdx | 39 ++++++++++++++++++ docs/ai-agents/plugins/native/morpho.mdx | 48 ++++++++++++++++++++++ docs/ai-agents/plugins/native/uniswap.mdx | 39 ++++++++++++++++++ docs/docs.json | 11 ++++- 6 files changed, 187 insertions(+), 9 deletions(-) create mode 100644 docs/ai-agents/plugins/native/avantis.mdx create mode 100644 docs/ai-agents/plugins/native/moonwell.mdx create mode 100644 docs/ai-agents/plugins/native/morpho.mdx create mode 100644 docs/ai-agents/plugins/native/uniswap.mdx diff --git a/docs/ai-agents/plugins/native-plugins.mdx b/docs/ai-agents/plugins/native-plugins.mdx index 628be9de0..6d0fa61f1 100644 --- a/docs/ai-agents/plugins/native-plugins.mdx +++ b/docs/ai-agents/plugins/native-plugins.mdx @@ -11,17 +11,17 @@ All four follow the same prepare → `send_calls` contract described in the [Ove ## The plugins - - Lending and vaults on Base. Uses Morpho's sibling MCP server at `mcp.morpho.org` for `prepare_*` tools that return simulated, unsigned calldata. 17 tools across read, write, and simulate. + + Lending and vaults on Base via Morpho's sibling MCP server. Deposit, borrow, withdraw, supply/withdraw collateral. - - Lending on Base and Optimism. Uses `web_request` against `api.moonwell.fi` to fetch ordered transactions — approve, enter-market, action — executed atomically through `send_calls`. + + Compound v2 lending on Base and Optimism. Supply, borrow, withdraw, repay — approval and action batched into one approval. - - Token swaps and V2/V3/V4 LP positions on Base. Uses `web_request` against the Uniswap trade API for quote, approval, and swap calldata. + + Token swaps (proxy-approval, no Permit2) and V2/V3/V4 LP position management on Base. - - Perpetual futures on Base. Uses `web_request` against the Avantis tx-builder for open, close, update, and limit-order calldata. + + Perpetual futures on Base. Open, close, manage margin, set TP/SL, plus market, limit, stop-limit, and zero-fee orders. diff --git a/docs/ai-agents/plugins/native/avantis.mdx b/docs/ai-agents/plugins/native/avantis.mdx new file mode 100644 index 000000000..8b9ccf71e --- /dev/null +++ b/docs/ai-agents/plugins/native/avantis.mdx @@ -0,0 +1,43 @@ +--- +title: "Avantis" +description: "Perpetual futures on Base via the Avantis tx-builder" +keywords: ["Avantis plugin", "Base MCP Avantis", "perpetual futures Base", "Avantis perps", "Base perps trading"] +--- + +Avantis is a perpetual futures DEX on Base mainnet. The plugin fetches unsigned calldata from the Avantis tx-builder (`tx-builder.avantisfi.com`) and executes it through Base MCP's `send_calls`. Collateral is USDC; ETH is used only for gas and execution fees. + +**Chain:** Base mainnet. + +**Operations:** open trade (market, limit, stop-limit, zero-fee), close, cancel, update margin, set TP/SL, approve USDC, set/remove delegate, plus reads for pairs, positions, limit orders, and PnL history. + +## Try it + +```text Open long +Open a 10x long BTC/USD with 100 USDC collateral on Avantis +``` + +```text Limit order +Place a limit long on ETH/USD at 3000 with 50 USDC at 5x +``` + +```text Close +Close my BTC/USD position on Avantis +``` + +```text Set TP/SL +Set TP to 100000 and SL to 80000 on my BTC long +``` + +## Pattern + +Every prepare endpoint returns a single-call envelope (`{ ok, data: { to, value, data, chainId } }`) that maps directly to `send_calls`. Approval and trade can be batched into one approval. The plugin reads `/v2/trading` to validate pair, leverage, and minimum notional before building the open call, and reads `core /user-data` to resolve real position/order indices for management actions. + + +`tx-builder.avantisfi.com`, `data.avantisfi.com`, `core.avantisfi.com`, and `api.avantisfi.com` must be on the Base MCP `web_request` allowlist. They already are for the hosted MCP at `mcp.base.org`. + + +## Reference + + + Endpoint inventory, parameters, unit/scaling rules, batching guidance, and error handling. + diff --git a/docs/ai-agents/plugins/native/moonwell.mdx b/docs/ai-agents/plugins/native/moonwell.mdx new file mode 100644 index 000000000..13cf3c184 --- /dev/null +++ b/docs/ai-agents/plugins/native/moonwell.mdx @@ -0,0 +1,39 @@ +--- +title: "Moonwell" +description: "Compound v2 lending on Base and Optimism via the Moonwell HTTP API" +keywords: ["Moonwell plugin", "Base MCP Moonwell", "Moonwell lending", "Compound v2 Base", "Moonwell borrow"] +--- + +Moonwell is a Compound v2 lending protocol on Base and Optimism. The plugin reads positions and rates from `api.moonwell.fi` and prepares unsigned calldata that Base MCP executes atomically through `send_calls` — including the `approve` and `enter-market` steps that precede each action. + +**Chains:** Base (8453), Optimism (10). + +**Operations:** supply, withdraw, borrow, repay, plus reads for markets, rates, positions, health, rewards, and token balances. + +## Try it + +```text Supply +Supply 100 USDC on Moonwell +``` + +```text Borrow +Borrow 500 USDC against my collateral on Moonwell +``` + +```text Health check +What's my Moonwell health factor on Base? +``` + +## Pattern + +The Moonwell API returns an ordered `transactions[]` array — `approve`, `enter-market`, then the protocol action. The plugin maps all entries into a single `send_calls` batch so the user approves once. + + +`api.moonwell.fi` must be on the Base MCP `web_request` allowlist. It already is for the hosted MCP at `mcp.base.org`. + + +## Reference + + + Endpoint inventory, response shapes, mToken notes, and health factor guide. + diff --git a/docs/ai-agents/plugins/native/morpho.mdx b/docs/ai-agents/plugins/native/morpho.mdx new file mode 100644 index 000000000..8365d7add --- /dev/null +++ b/docs/ai-agents/plugins/native/morpho.mdx @@ -0,0 +1,48 @@ +--- +title: "Morpho" +description: "Lending and vaults on Base via Morpho's sibling MCP server" +keywords: ["Morpho plugin", "Base MCP Morpho", "Morpho lending", "Morpho vaults", "Base lending"] +--- + +Morpho is a lending protocol on Base. The plugin drives the [Morpho MCP server](https://mcp.morpho.org/) for vault discovery, position queries, and prepare-style tools that return unsigned calldata. Base MCP's `send_calls` wraps the calldata into a single approval. + +**Chain:** Base mainnet. + +**Operations:** deposit, withdraw, supply, borrow, repay, supply/withdraw collateral, plus reads for vaults, markets, and positions. + +## Install alongside Base MCP + +```json mcp.json +{ + "mcpServers": { + "base-account": { "url": "https://mcp.base.org" }, + "morpho": { "url": "https://mcp.morpho.org/" } + } +} +``` + +Claude Code: `claude mcp add morpho --transport http https://mcp.morpho.org/` + +## Try it + +```text Find a vault +Find the best USDC vault on Base by APY and deposit 100 USDC +``` + +```text Check positions +Show all my Morpho positions on Base +``` + +```text Health check +Check if my Morpho borrow position is healthy +``` + +## Pattern + +Morpho's `prepare_*` tools return `{ calls, chainId }` — passed straight to `send_calls`, which returns an approval URL. The assistant polls `get_request_status` once you confirm. + +## Reference + + + Tool inventory, response shapes, and orchestration details. + diff --git a/docs/ai-agents/plugins/native/uniswap.mdx b/docs/ai-agents/plugins/native/uniswap.mdx new file mode 100644 index 000000000..f857f06d5 --- /dev/null +++ b/docs/ai-agents/plugins/native/uniswap.mdx @@ -0,0 +1,39 @@ +--- +title: "Uniswap" +description: "Token swaps and V2/V3/V4 LP positions on Base via the Uniswap trade and liquidity APIs" +keywords: ["Uniswap plugin", "Base MCP Uniswap", "Uniswap swap Base", "Uniswap LP", "Uniswap V4 Base"] +--- + +The Uniswap plugin covers token swaps (proxy-approval flow, no Permit2 signing) and LP position management for V2, V3, and V4 on Base. It fetches unsigned calldata from Uniswap's trade and liquidity APIs and executes it through Base MCP's `send_calls`. + +**Chain:** Base mainnet. + +**Operations:** swap quote/approval/execute; create, increase, decrease V3/V4 positions; create V2 positions; collect LP fees. + +## Try it + +```text Swap +Swap 100 USDC for ETH on Base +``` + +```text Create LP +Create a V4 ETH/USDC LP position on Base with 0.1 ETH +``` + +```text Collect fees +Collect fees from my Uniswap LP positions +``` + +## Pattern + +Swap flow is three calls — `/check_approval`, `/quote`, `/swap` — batched into one `send_calls` so approval and swap execute together. LP flow follows the same shape: `/lp/pool_info` (if needed), `/lp/check_approval`, then the action endpoint (`/lp/create`, `/lp/increase`, `/lp/decrease`, `/lp/claim_fees`). + + +`trade-api.gateway.uniswap.org` and `liquidity.api.uniswap.org` must be on the Base MCP `web_request` allowlist. They already are for the hosted MCP at `mcp.base.org`. + + +## Reference + + + Endpoint inventory, headers, response shapes, and orchestration for swap and LP flows. + diff --git a/docs/docs.json b/docs/docs.json index 6e054eaac..a5d6b3905 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -697,7 +697,16 @@ "group": "Skill & Plugins [WIP]", "pages": [ "ai-agents/plugins/index", - "ai-agents/plugins/native-plugins", + { + "group": "Native Plugins", + "pages": [ + "ai-agents/plugins/native-plugins", + "ai-agents/plugins/native/morpho", + "ai-agents/plugins/native/moonwell", + "ai-agents/plugins/native/uniswap", + "ai-agents/plugins/native/avantis" + ] + }, "ai-agents/plugins/custom-plugins" ] } From 13900e7ccb49a27d68f7fb73f754730d53e8d78f Mon Sep 17 00:00:00 2001 From: Youssef Date: Thu, 21 May 2026 18:31:58 +0100 Subject: [PATCH 32/36] update chatgpt flow --- docs/ai-agents/quickstart.mdx | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index 068b49ffa..5b5a0ace0 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -150,26 +150,21 @@ import { AuthApprovalDemo } from "/snippets/AuthApprovalDemo.jsx" Claude activates the skill automatically when relevant to your prompt. See [Use skills in Claude](https://support.claude.com/en/articles/12512180-use-skills-in-claude) for details. - Skills in ChatGPT are only available on **Business, Enterprise, Edu, Teachers, and Healthcare** plans. If you're on another plan, use the **Copy prompt** option below — it works on any ChatGPT plan. - - **Option 1: Copy prompt (any plan)** + + Download for ChatGPT + - - Read this skill and its plugins, check if I have the Base MCP installed, and onboard me by following the contents of this zip file: `https://github.com/base/skills/raw/refs/heads/youssef/add-build-on-base-and-base-mcp/skills/base-mcp/base-mcp-v0.1.1.zip` - + Click the button above to download `base-mcp.zip`, then pick one: - Paste it into a new ChatGPT conversation. ChatGPT will fetch the skill, verify your Base MCP connection, and walk you through setup. + **Option 1: Drop the zip into a conversation** - **Option 2: Upload skill (Business, Enterprise, Edu, Teachers, Healthcare plans)** + Attach the downloaded `base-mcp.zip` to a new ChatGPT conversation and ask ChatGPT to read the skill and onboard you. Works on any ChatGPT plan — quickest way to try it without changing any settings. - - Download for ChatGPT - + **Option 2: Install as a persistent skill (Business, Enterprise, Edu, Teachers, Healthcare plans)** - 1. Click the button above to download `base-mcp.zip` - 2. In ChatGPT, open [**Settings → Skills**](https://chatgpt.com/skills) - 3. Click **Add skill** and upload the downloaded `base-mcp.zip` - 4. Enable the skill for the conversations where you want it active + 1. In ChatGPT, open [**Settings → Skills**](https://chatgpt.com/skills) + 2. Click **Add skill** and upload the downloaded `base-mcp.zip` + 3. Enable the skill for the conversations where you want it active See [Skills in ChatGPT](https://help.openai.com/en/articles/20001066-skills-in-chatgpt) for details. From d178f1cb4bcb57b830dd316c2eaaac90ee76d69b Mon Sep 17 00:00:00 2001 From: Youssef Date: Thu, 21 May 2026 18:33:38 +0100 Subject: [PATCH 33/36] update language --- docs/ai-agents/quickstart.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index 5b5a0ace0..d0b4731d0 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -158,7 +158,7 @@ import { AuthApprovalDemo } from "/snippets/AuthApprovalDemo.jsx" **Option 1: Drop the zip into a conversation** - Attach the downloaded `base-mcp.zip` to a new ChatGPT conversation and ask ChatGPT to read the skill and onboard you. Works on any ChatGPT plan — quickest way to try it without changing any settings. + Attach the downloaded `base-mcp.zip` to a new ChatGPT conversation and ask ChatGPT to read the skill and onboard you. Works on any ChatGPT plan, the quickest way to try it without changing any settings. **Option 2: Install as a persistent skill (Business, Enterprise, Edu, Teachers, Healthcare plans)** From 50e0194cfc93e64eca613d5e8efb92ff1e00335d Mon Sep 17 00:00:00 2001 From: Youssef Date: Thu, 21 May 2026 19:03:19 +0100 Subject: [PATCH 34/36] add skills md files --- .../{native-plugins.mdx => native/index.mdx} | 2 +- docs/ai-agents/skills/README.md | 26 + docs/ai-agents/skills/SKILL.md | 70 +++ docs/ai-agents/skills/plugins/avantis.md | 547 ++++++++++++++++++ docs/ai-agents/skills/plugins/moonwell.md | 163 ++++++ docs/ai-agents/skills/plugins/morpho.md | 72 +++ docs/ai-agents/skills/plugins/uniswap.md | 470 +++++++++++++++ .../skills/references/approval-mode.md | 29 + .../skills/references/batch-calls.md | 40 ++ .../skills/references/custom-plugins.md | 49 ++ docs/ai-agents/skills/references/install.md | 159 +++++ docs/ai-agents/skills/references/tone.md | 49 ++ docs/docs.json | 2 +- 13 files changed, 1676 insertions(+), 2 deletions(-) rename docs/ai-agents/plugins/{native-plugins.mdx => native/index.mdx} (99%) create mode 100644 docs/ai-agents/skills/README.md create mode 100644 docs/ai-agents/skills/SKILL.md create mode 100644 docs/ai-agents/skills/plugins/avantis.md create mode 100644 docs/ai-agents/skills/plugins/moonwell.md create mode 100644 docs/ai-agents/skills/plugins/morpho.md create mode 100644 docs/ai-agents/skills/plugins/uniswap.md create mode 100644 docs/ai-agents/skills/references/approval-mode.md create mode 100644 docs/ai-agents/skills/references/batch-calls.md create mode 100644 docs/ai-agents/skills/references/custom-plugins.md create mode 100644 docs/ai-agents/skills/references/install.md create mode 100644 docs/ai-agents/skills/references/tone.md diff --git a/docs/ai-agents/plugins/native-plugins.mdx b/docs/ai-agents/plugins/native/index.mdx similarity index 99% rename from docs/ai-agents/plugins/native-plugins.mdx rename to docs/ai-agents/plugins/native/index.mdx index 6d0fa61f1..9addf8f97 100644 --- a/docs/ai-agents/plugins/native-plugins.mdx +++ b/docs/ai-agents/plugins/native/index.mdx @@ -1,5 +1,5 @@ --- -title: "Native Plugins" +title: "Overview" description: "Plugins authored by the Base team that ship with the Base MCP skill" keywords: ["Base MCP plugins", "Morpho plugin", "Moonwell plugin", "Uniswap plugin", "Avantis plugin"] --- diff --git a/docs/ai-agents/skills/README.md b/docs/ai-agents/skills/README.md new file mode 100644 index 000000000..95c45820a --- /dev/null +++ b/docs/ai-agents/skills/README.md @@ -0,0 +1,26 @@ +--- +title: "Base MCP Skill — Disclaimer" +description: "Terms, risks, and limitations for using the Base MCP skill with AI agents." +--- + +# Base MCP — Disclaimer + +> ⚠️ **Important: Read Before Use** + +**What this is.** The Base MCP is a hosted Model Context Protocol server operated by Base that lets AI agents interact with a user's Base Account in a user-authorized way. After authenticating and connecting to the MCP server, the MCP server can read account state and construct transactions for the user to approve and sign. The MCP server itself does not sign or broadcast transactions. By using this MCP server, you agree to the Base Account and Base App Terms of Service. + +**Third-party AI hosts, agents, and protocols.** The Base MCP is designed to be used with third-party AI hosts and may, depending on the skills loaded into the AI host, prepare transactions that interact with third-party onchain protocols. Those AI hosts and third-party protocols are not operated by Base and are governed by their own terms of service, privacy policies, and (where applicable) jurisdictional eligibility requirements. You are solely responsible for reviewing and complying with each third party's terms and confirming you are eligible to use them. + +**Not official third-party software.** Skills or plugins in the base-skills repo that reference third-party protocols (e.g., Uniswap, Morpho, Moonwell, Avantis) are authored by Base for use with the Base MCP. They are not official software of, endorsed by, or operated by those third parties. Inclusion of a skill in this repository does not constitute an endorsement, audit, or guarantee of the underlying protocol. Each third-party protocol is governed by its own terms of service and privacy policy, which the user is solely responsible for reviewing and complying with. + +**AI outputs may be inaccurate.** AI agents can misinterpret instructions, hallucinate parameters (including amounts, recipients, and contract addresses), or be influenced by adversarial inputs encountered in API responses, web content, or other sources. The Base MCP relies on the AI agent to interpret your intent correctly. Base does not validate or guarantee AI agent outputs. Review every action proposed by an AI agent before approving it. + +**Not professional advice.** Nothing produced by or in connection with the Base MCP — including any output of an AI agent using the service — constitutes investment, financial, legal, tax, or other professional advice. + +**Your responsibility for compliance.** You are solely responsible for ensuring that your use of the Base MCP, any connected AI host or agent, your wallet, and any third-party protocol complies with all laws and regulations applicable to you, including sanctions, securities, derivatives, tax, and consumer protection laws. + +**Smart contract and onchain risk.** Interacting with onchain protocols may result in partial or total loss of funds due to smart contract vulnerabilities, oracle failures, liquidations, slippage, MEV, governance actions, network congestion, protocol shutdowns, or other risks. Base does not control any third-party onchain protocol that you choose to interact with through the Base MCP. + +**Service availability and changes.** The Base MCP is provided "AS IS" and "AS AVAILABLE." Base may modify, suspend, or discontinue the service or any feature of it at any time and with or without notice. Base does not warrant that the service will be error-free, uninterrupted, secure, or compatible with any particular AI host, wallet, or third-party protocol. + +**Limitation of liability.** To the maximum extent permitted by applicable law, Base and its affiliates and their respective officers, directors, employees, and agents will not be liable for any indirect, incidental, special, consequential, exemplary, or punitive damages, or for any loss of profits, revenues, data, or digital assets, arising out of or related to your use of (or inability to use) the Base MCP or any third-party AI host, agent, or protocol used in connection with it, whether based on warranty, contract, tort (including negligence), statute, or any other legal theory. diff --git a/docs/ai-agents/skills/SKILL.md b/docs/ai-agents/skills/SKILL.md new file mode 100644 index 000000000..acdfaae8f --- /dev/null +++ b/docs/ai-agents/skills/SKILL.md @@ -0,0 +1,70 @@ +--- +title: "Base MCP Skill" +description: "Base MCP — gives your AI assistant access to a Base account via the Base MCP server (mcp.base.org). Wallet, portfolio, sending, swapping, signing, batched contract calls, and transaction history on Base." +name: base-mcp +version: 0.1.0 +--- + +# Base MCP + +> [!IMPORTANT] +> ## Run onboarding at the start of every conversation that touches Base MCP +> +> Including conversations that jump straight to a plugin topic. Onboarding is short — see below. + +## Detection + +The Base MCP exposes its tools to the harness when connected. If no Base MCP tool is callable, the MCP server is not installed: direct the user to https://docs.base.org/ai-agents/quickstart (or load [references/install.md](references/install.md) for app-specific steps) and stop. + +If Base MCP tools are available, load [references/tone.md](references/tone.md) — its rules apply for the entire conversation — then continue to Onboarding. + +## Onboarding + +Keep it short. Do this once per session, before doing real work: + +1. **Briefly mention what's available** — one or two sentences. The user has a Base account wallet and can do things like check balances, send and swap tokens, sign messages, batch contract calls, and (if installed) use partner plugins for DeFi, swaps, and other onchain actions. Do not enumerate every tool — the agent discovers tools and plugins directly from the MCP. + +2. **Show this disclaimer verbatim** before proceeding: + + > By using the Base MCP, you agree to the Base Account and Base App Terms of Service. Plugins available in the Base repo are authored by Base, not by the third-party protocols they reference. + +3. **Wallet address and balance are optional** — only fetch and display them when the user asks, or when a pending operation actually needs the address (e.g., a write call, a position lookup). Don't volunteer a wallet dump up front. + +## Tools + +The Base MCP advertises its own tool catalog to the harness. Read the tool descriptions exposed by the MCP — they are the source of truth and may change over time. Do not assume a fixed list; do not preload a tool catalog from this skill. + +Two patterns deserve their own references because they span multiple tools: + +| Topic | Reference | +|-------|-----------| +| Approval flow (for any write tool that returns an approval URL) | [references/approval-mode.md](references/approval-mode.md) | +| Batched contract calls (EIP-5792) | [references/batch-calls.md](references/batch-calls.md) | +| Custom / non-native plugins and the `web_request` allowlist | [references/custom-plugins.md](references/custom-plugins.md) | +| Platform install steps | [references/install.md](references/install.md) | +| Tone and language rules | [references/tone.md](references/tone.md) | + +## Plugins + +Plugins extend Base MCP with partner-specific functionality (lending, swaps, perps, etc.). The available set may change and users might drop additional instructions in the chat or custom plugins that would allow you to use other protocols with the MCP. + +Plugins currently maintained alongside this skill (the **native plugins**): + +| Plugin | Reference | +|--------|-----------| +| Morpho | [plugins/morpho.md](plugins/morpho.md) | +| Moonwell | [plugins/moonwell.md](plugins/moonwell.md) | +| Uniswap | [plugins/uniswap.md](plugins/uniswap.md) | +| Avantis | [plugins/avantis.md](plugins/avantis.md) | + +Load a plugin reference only when the user's request matches it. For a plugin's own tools, defer to the descriptions the plugin's MCP exposes — this skill does not duplicate them. + +### Native plugins vs. custom / user-supplied plugins + +Native plugins are allowlisted in the Base MCP `web_request` tool and work everywhere. Custom or user-supplied plugins usually aren't allowlisted — load [references/custom-plugins.md](references/custom-plugins.md) for the decision tree on which HTTP path to use (harness HTTP tool vs. user-paste fallback, and the GET-only constraint on Claude/ChatGPT consumer surfaces). + +## Installation + +```bash +npx skills add base/skills --skill base-mcp +``` diff --git a/docs/ai-agents/skills/plugins/avantis.md b/docs/ai-agents/skills/plugins/avantis.md new file mode 100644 index 000000000..ee34b4307 --- /dev/null +++ b/docs/ai-agents/skills/plugins/avantis.md @@ -0,0 +1,547 @@ +--- +title: "Avantis Plugin" +description: "Skill plugin reference for trading perpetual futures on Avantis through Base MCP." +--- + +# Avantis Plugin + +> [!IMPORTANT] +> Complete the short Base MCP onboarding flow defined in `SKILL.md` before calling any Avantis endpoint. The user's wallet address — used as `trader` in every tx-builder call — is fetched lazily when needed. + +Avantis is a perpetual futures DEX on Base mainnet (`chainId` 8453). Use `web_request` to fetch unsigned calldata from the Avantis tx-builder, then preview or execute it with account MCP `send_calls`. + +Do not sign, approve, or submit transactions unless the user explicitly asks. Generating calldata and `send_calls` approval links is safe, but the user must approve any real transaction. + +Prerequisite: `tx-builder.avantisfi.com`, `data.avantisfi.com`, `core.avantisfi.com`, and `api.avantisfi.com` must be in the account MCP `web_request` allowlist. + +No API key or Authorization header is required for the documented public endpoints. + +--- + +## API Services + +| Service | Base URL | Purpose | +| --- | --- | --- | +| tx-builder | `https://tx-builder.avantisfi.com` | GET-only unsigned calldata builder for Avantis Trading and USDC calls | +| data | `https://data.avantisfi.com/v2/trading` | Pair configs, leverage rules, fees, open interest, market status | +| core | `https://core.avantisfi.com` | Current open positions, limit orders, and open interest | +| history | `https://api.avantisfi.com` | Closed/all trade history, PnL, referral stats, market-order settlement status | + +Source of truth for tx-builder shape: + +``` +GET https://tx-builder.avantisfi.com/openapi.json +GET https://tx-builder.avantisfi.com/docs +``` + +--- + +## Base-Only Rules + +- All tx-builder calldata is for Base mainnet only. +- All tx-builder responses return `chainId: 8453`. +- There is no supported chain selector query parameter. +- Collateral is USDC only. ETH is used only for gas and Avantis execution fee `value`. +- Canonical Base USDC: `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`. +- Default USDC spender is Avantis `TradingStorage`: `0x8a311D7048c35985aa31C131B9A13e03a5f7422d`. + +Fetch current contract addresses when needed: + +``` +GET https://tx-builder.avantisfi.com/addresses +``` + +--- + +## tx-builder Response Shape + +All calldata-producing tx-builder endpoints return an envelope: + +```json +{ + "ok": true, + "data": { + "to": "0x44914408af82bC9983bbb330e3578E1105e11d4e", + "from": "0x1111111111111111111111111111111111111111", + "data": "0x19cde9a1...", + "value": "0x13e52b9abe000", + "chainId": 8453, + "description": "Open long BTC/USD 10x with 100 USDC (market)", + "meta": {} + } +} +``` + +Only `response.data.to`, `response.data.value`, and `response.data.data` are passed to account MCP `send_calls`. + +```json +{ + "chain": "base", + "calls": [ + { + "to": "", + "value": "", + "data": "" + } + ] +} +``` + +`from` is informational and identifies who must sign. If `delegate=` is used, `from` becomes the delegate address. `nonce` and gas fields are intentionally omitted; the wallet manages them. + +--- + +## Units And Scaling + +tx-builder request inputs use human decimals: + +| Surface | Unit behavior | +| --- | --- | +| tx-builder `collateralUsdc`, `amountUsdc`, `openPrice`, `takeProfit`, `stopLoss`, `leverage`, `slippagePercent` | Human decimals, not raw scaled integers | +| data API `/v2/trading` | Human decimals | +| core `/user-data` positions and limit orders | Raw strings: USDC fields divide by `1e6`, price and leverage fields divide by `1e10` | +| history API | Mixed, mostly human decimals; check each endpoint shape | +| tx-builder response `value` | Hex wei string | + +Do not pass `1e6` USDC base units or `1e10` price units to tx-builder query parameters. + +--- + +## Orchestration Pattern + +For an open trade: + +``` +get_wallets -> trader address +web_request GET /v2/trading -> validate pair, market status, leverage, and min position +web_request GET /user-data?trader=... -> inspect existing positions/orders +web_request GET /token/approve if allowance may be missing -> send_calls preview +web_request GET /trade/open -> send_calls preview +poll /v2/market-order-initiated/status/ only after a real tx is submitted +web_request GET /user-data?trader=... -> confirm final state only after execution +``` + +For management actions (close, cancel, margin, TP/SL), always read `core /user-data` first and use a real `positions[].index` or `limitOrders[].index`. The tx-builder can encode calldata for a requested index even if that position/order does not exist, so preflight is required to avoid likely reverts. + +--- + +## Step 1 - Validate Pair, Leverage, Liquidity + +``` +GET https://data.avantisfi.com/v2/trading +``` + +Top-level shape: + +```json +{ + "dataVersion": 1.5, + "pairInfos": { "1": {} }, + "groupInfo": { "0": {} }, + "pairCount": 102 +} +``` + +Use `pairInfos[""]` to inspect a pair. Important fields: + +| Field | Meaning | +| --- | --- | +| `index` | Pair index used by tx-builder and onchain calls | +| `from`, `to` | Symbol components, for example `BTC` and `USD` | +| `isPairListed` | Must be true to open new trades | +| `leverages.minLeverage`, `leverages.maxLeverage` | Fixed-fee leverage envelope for `market`, `limit`, `stop_limit` | +| `leverages.pnlMinLeverage`, `leverages.pnlMaxLeverage` | ZFP leverage envelope for `market_zero_fee` | +| `pairMinLevPosUSDC` | Minimum notional: `collateralUsdc * leverage` | +| `pairOI`, `pairMaxOI` | Pair open interest and cap | +| `groupIndex` | Lookup key into `groupInfo` | +| `feed.attributes.is_open` or `feed.attributes.isOpen` | Market-open flag | +| `lazerFeed.state` | `stable` generally maps to `priceSourcing=1` for Lazer endpoints | + +Minimum position check (BELOW_MIN_POS): + +The tx-builder rejects with `400 BAD_REQUEST` when `collateralUsdc * leverage < pairMinLevPosUSDC`. This is the `BELOW_MIN_POS` condition. Always validate before calling `/trade/open`: + +``` +positionSize = collateralUsdc * leverage +if positionSize < pair.pairMinLevPosUSDC -> BELOW_MIN_POS error, increase collateral or leverage +``` + +To compute the minimum collateral required for a given leverage: + +``` +minCollateral = ceil(pair.pairMinLevPosUSDC / leverage) +``` + +Example: `pairMinLevPosUSDC=100`, `leverage=10` → minimum `collateralUsdc` is `10`. With `leverage=1` → minimum is `100`. + +Liquidity check: + +``` +pairAvailable = pairMaxOI - pairOI +groupAvailable = groupInfo[pair.groupIndex].groupMaxOI - groupInfo[pair.groupIndex].groupOI +available = min(pairAvailable, groupAvailable) +positionSize = collateralUsdc * leverage +``` + +For BTC/USD around a small test amount, `collateralUsdc=1` and `leverage=100` can satisfy the 100 USDC minimum notional for `market_zero_fee` when 100x is inside the ZFP leverage range. + +--- + +## Step 2 - Check User Positions And Limit Orders + +``` +GET https://core.avantisfi.com/user-data?trader=
+``` + +Response: + +```json +{ + "positions": [], + "limitOrders": [] +} +``` + +Key fields: + +| Field | Scaling | Use | +| --- | --- | --- | +| `pairIndex` | none | tx-builder `pairIndex` | +| `index` | none | tx-builder `tradeIndex` | +| `buy` | none | `true` is long, `false` is short | +| `collateral` | divide by `1e6` | Use as `collateralUsdc` when closing full size | +| `leverage` | divide by `1e10` | Display and validation | +| `openPrice`, `tp`, `sl`, `liquidationPrice` | divide by `1e10` | Display and TP/SL decisions | +| `isPnl` | none | true means ZFP trade | + +Unknown or malformed traders can return empty arrays rather than an error. + +--- + +## Step 3 - Approve USDC + +Exact approval: + +``` +GET https://tx-builder.avantisfi.com/token/approve + ?trader=
+ &amountUsdc=1 +``` + +Unlimited approval: + +``` +GET https://tx-builder.avantisfi.com/token/approve?trader=
+``` + +Optional custom spender: + +``` +GET https://tx-builder.avantisfi.com/token/approve + ?trader=
+ &amountUsdc=100 + &spender=
+``` + +`spender` defaults to `TradingStorage`. Pass the returned `response.data` call to `send_calls`. Approval must be confirmed onchain before trade calls that require allowance can succeed, unless approval and action are submitted as a valid batch and the wallet/account contract supports the batch. + +--- + +## Step 4 - Open A Trade + +``` +GET https://tx-builder.avantisfi.com/trade/open + ?trader=
+ &pair=BTC/USD + &side=long + &orderType=market + &collateralUsdc=100 + &leverage=10 + &slippagePercent=1 +``` + +Parameters: + +| Parameter | Required | Notes | +| --- | --- | --- | +| `trader` | yes | EVM address that owns the position | +| `pair` or `pairIndex` | yes | Pair symbols accept `/`, `-`, or `_`, for example `BTC/USD`, `btc-usd`, `BTC_USD` | +| `side` | yes | `long` or `short` | +| `orderType` | no | `market`, `limit`, `stop_limit`, or `market_zero_fee`; default is `market` | +| `collateralUsdc` | yes | Human-decimal USDC, must be greater than zero | +| `leverage` | yes | Human multiplier; pair envelope is enforced | +| `slippagePercent` | no | Human percent, default `1`; must be greater than 0 and <= 100 | +| `openPrice` | required for limit/stop_limit | Human-decimal price; optional market override | +| `takeProfit` | no | Human-decimal TP price | +| `stopLoss` | no | Human-decimal SL price | +| `executionFeeEth` | no | Default about `0.00035` ETH; max 1 ETH | +| `delegate` | no | Wraps call in `Trading.delegatedAction(trader, calldata)` | +| `skipValidation` | no | `true` bypasses pre-trade checks; avoid unless explicitly requested | + +Order types: + +| `orderType` | Meaning | +| --- | --- | +| `market` | Fixed-fee market open; price is auto-resolved if `openPrice` omitted | +| `limit` | Limit order; `openPrice` required | +| `stop_limit` | Stop-limit order; `openPrice` required | +| `market_zero_fee` | Zero-Fee Protocol / ZFP market open; uses `pnlMinLeverage` and `pnlMaxLeverage` | + +Example ZFP around a small notional: + +``` +GET https://tx-builder.avantisfi.com/trade/open + ?trader=
+ &pair=BTC/USD + &side=long + &orderType=market_zero_fee + &collateralUsdc=1 + &leverage=100 + &slippagePercent=1 +``` + +Example limit: + +``` +GET https://tx-builder.avantisfi.com/trade/open + ?trader=
+ &pair=BTC/USD + &side=long + &orderType=limit + &openPrice=90000 + &collateralUsdc=2 + &leverage=50 + &takeProfit=100000 + &stopLoss=80000 +``` + +--- + +## Step 5 - Close, Cancel, Margin, TP/SL + +Read `core /user-data` first. Use real indices from the returned arrays. + +Close full or partial collateral: + +``` +GET https://tx-builder.avantisfi.com/trade/close + ?trader=
+ &pairIndex= + &tradeIndex= + &collateralUsdc= +``` + +Cancel a resting limit or stop-limit order: + +``` +GET https://tx-builder.avantisfi.com/trade/cancel + ?trader=
+ &pairIndex= + &tradeIndex= +``` + +Deposit or withdraw margin: + +``` +GET https://tx-builder.avantisfi.com/margin/update + ?trader=
+ &pairIndex= + &tradeIndex= + &action=deposit + &collateralUsdc=1 +``` + +`action` is `deposit` or `withdraw`. If `priceUpdateData` and `priceSourcing` are omitted, tx-builder fetches required Pyth bytes server-side. + +Set TP and SL together: + +``` +GET https://tx-builder.avantisfi.com/tpsl/update + ?trader=
+ &pairIndex= + &tradeIndex= + &takeProfit=100000 + &stopLoss=80000 +``` + +`takeProfit` is required and must be greater than zero. `stopLoss` is required; pass `stopLoss=0` to clear SL. + +Open limit order modification is not exposed as a current tx-builder endpoint. To replace a resting limit order, cancel the existing order with `/trade/cancel`, then create a new `/trade/open` limit or stop-limit order. + +--- + +## Delegated Trading + +Set a delegate: + +``` +GET https://tx-builder.avantisfi.com/delegate/set + ?trader=
+ &delegate= +``` + +Remove a delegate: + +``` +GET https://tx-builder.avantisfi.com/delegate/remove?trader=
+``` + +After a delegate is set, trade-side tx-builder endpoints accept `delegate=`. The response `from` becomes the delegate, and the delegate signs/broadcasts. The position still belongs to `trader`. + +--- + +## Batching With send_calls + +`send_calls` accepts multiple Base calls: + +```json +{ + "chain": "base", + "calls": [ + { + "to": "", + "value": "", + "data": "" + }, + { + "to": "", + "value": "", + "data": "" + } + ] +} +``` + +Useful preview batches: + +- Approval plus open trade. +- Approval plus margin deposit. +- Cancel resting order plus create replacement limit order. +- Multiple independent generated calls, if all are Base calls and logically safe to preview together. + +Keep approval before the action that needs allowance. Do not combine calls from different chains. + +--- + +## Settlement Polling + +Market opens and closes settle after the submitted transaction emits an initiated event. Only poll when you have a real tx hash from a submitted transaction. + +``` +GET https://api.avantisfi.com/v2/market-order-initiated/status/ +``` + +Expected logical statuses: + +- `executed` +- `canceled` +- `pending` + +Unknown hashes can return HTTP 200 with: + +```json +{ + "success": false, + "errorMessage": "Market order not found for the given transaction hash" +} +``` + +Use exponential backoff and stop after a reasonable timeout. Do not claim a position opened or closed until onchain state or the settlement API confirms it. + +--- + +## Query Trade History And PnL + +History endpoints use a legacy envelope: + +```json +{ "success": true } +{ "success": false, "errorMessage": "..." } +``` + +Always check `success` before reading data. + +| Endpoint | Purpose | +| --- | --- | +| `GET https://api.avantisfi.com/v2/history/portfolio/history/
/0/20` | Closed trades, paginated; limit max 20 | +| `GET https://api.avantisfi.com/v2/history/portfolio/all/
/0/20` | All trades, open and closed | +| `GET https://api.avantisfi.com/v2/history/portfolio/top/
` | Top 3 by net PnL | +| `GET https://api.avantisfi.com/v2/history/portfolio/top/
/5` | Top N by net PnL | +| `GET https://api.avantisfi.com/v2/history/portfolio/profit-loss/
` | Aggregate PnL | +| `GET https://api.avantisfi.com/v2/history/portfolio/profit-loss/
/grouped` | Aggregate PnL by pair | +| `GET https://api.avantisfi.com/v2/history/referral/stats/
` | Referral stats | + +Observed edge case: for a wallet with no visible portfolio, some history endpoints may return `success:false` with `Unable to get the portfolio.` while others return `success:true` with empty data. Treat this as an empty/unknown portfolio unless the user expected existing history. + +PnL convention: + +- For ZFP trades, prefer `_mapped_netPnl` where present. +- For fixed-fee trades, prefer `_mapped_grossPnl` where present. + +--- + +## Error Handling + +tx-builder errors: + +```json +{ + "ok": false, + "error": { + "code": "BAD_REQUEST", + "message": "Position size 0.01 USDC is below the minimum of 100 USDC for BTC/USD (collateral 0.01 x leverage 1)" + } +} +``` + +Common tx-builder error codes: + +| Code | Meaning | +| --- | --- | +| `VALIDATION_ERROR` | Query shape problem: bad address, missing required field, numeric range error | +| `BAD_REQUEST` | Domain validation failed: min position, leverage envelope, liquidity, invalid TP/SL | +| `UPSTREAM_ERROR` | Data or price feed dependency failed | +| `NOT_FOUND` | Unknown route or pair index | +| `INTERNAL_ERROR` | Unexpected service error | + +Recommended handling: + +- Surface validation messages directly. +- For `/trade/open`, inspect `meta.validation` on success and show the user the position size, min position, leverage envelope, and available liquidity when useful. +- For history endpoints, check `success`; if false, show `errorMessage`. +- For management actions, do not rely on tx-builder to prove the position/order exists. Verify with `core /user-data`. + +BELOW_MIN_POS recovery: + +When the error message indicates a minimum position violation (`collateral * leverage < pairMinLevPosUSDC`), do not retry blindly. Compute what is needed and suggest corrections: + +``` +minPositionUsdc = pair.pairMinLevPosUSDC // from data API or meta.validation.minPositionUsdc +minCollateral = ceil(minPositionUsdc / requestedLeverage) +minLeverage = ceil(minPositionUsdc / requestedCollateral) +``` + +Present the user with concrete options: increase collateral to `minCollateral`, increase leverage to `minLeverage` (within the pair envelope), or both. Do not silently adjust parameters without user confirmation. + +--- + +## Current tx-builder Endpoint Inventory + +| Endpoint | Calldata? | Purpose | +| --- | --- | --- | +| `GET /` | No | Service index | +| `GET /health` | No | Health and chainId | +| `GET /addresses` | No | Contract addresses | +| `GET /pairs` | No | Pair summaries | +| `GET /pairs/` | No | Single pair details | +| `GET /trade/open` | Yes | Open market, ZFP, limit, or stop-limit trade | +| `GET /trade/close` | Yes | Close a trade | +| `GET /trade/cancel` | Yes | Cancel a resting limit or stop-limit order | +| `GET /margin/update` | Yes | Deposit or withdraw collateral | +| `GET /tpsl/update` | Yes | Update TP and SL | +| `GET /delegate/set` | Yes | Set delegate | +| `GET /delegate/remove` | Yes | Remove delegate | +| `GET /token/approve` | Yes | Approve USDC | +| `GET /docs` | No | Swagger UI | +| `GET /openapi.json` | No | OpenAPI spec | + diff --git a/docs/ai-agents/skills/plugins/moonwell.md b/docs/ai-agents/skills/plugins/moonwell.md new file mode 100644 index 000000000..36f61526d --- /dev/null +++ b/docs/ai-agents/skills/plugins/moonwell.md @@ -0,0 +1,163 @@ +--- +title: "Moonwell Plugin" +description: "Skill plugin reference for lending on Moonwell through Base MCP." +--- + +# Moonwell Plugin + +> [!IMPORTANT] +> Complete the short Base MCP onboarding flow defined in `SKILL.md` before calling any Moonwell endpoint. The user's wallet address — required for `prepare` and position queries — is fetched lazily when needed. + +Moonwell is a Compound v2 lending protocol on Base and Optimism. Use `web_request` to call the Moonwell HTTP API to read positions/rates and prepare unsigned calldata, then execute via `send_calls`. + +No additional MCP server required — everything goes through `web_request` + `send_calls`. + +**Prerequisite:** `api.moonwell.fi` must be in the MCP server's `web_request` allowlist. If requests to that hostname are rejected, inform the user that the Moonwell API is not yet whitelisted on this MCP instance. + +**Supported chains:** Base (8453), Optimism (10). + +--- + +## Orchestration Pattern + +``` +web_request(https://api.moonwell.fi/v1/prepare/?...) + → { data: { transactions: [ { to, data, value, chainId }, ... ] } } + ↓ +send_calls(chainId, calls mapped from transactions[]) + → approvalUrl + requestId + ↓ +User approves at the returned approval URL (present as "Approve Transaction" — see ../references/approval-mode.md) + ↓ +get_request_status(requestId) → confirmed +``` + +Steps in `transactions[]` are ordered — `approve` and `enter-market` come before the protocol action. Execute them as a single `send_calls` batch. + +--- + +## Read Endpoints (use web_request GET) + +``` +GET https://api.moonwell.fi/v1/markets?chain=base +GET https://api.moonwell.fi/v1/markets/USDC?chain=base +GET https://api.moonwell.fi/v1/rates?chain=base&asset=USDC +GET https://api.moonwell.fi/v1/yield?chain=base&sort=apy&min-tvl=1000000&limit=5 +GET https://api.moonwell.fi/v1/positions/
?chain=base +GET https://api.moonwell.fi/v1/health/
?chain=base +GET https://api.moonwell.fi/v1/rewards/
?chain=base +GET https://api.moonwell.fi/v1/token-balance/
?chain=base&asset=USDC +``` + +Market reads are edge-cached 30 s. User-scoped reads (`positions`, `health`, `rewards`, `token-balance`) are never cached. + +`/positions` returns an array — one entry per market. Use `?active=true` to filter out markets where both `suppliedUsd` and `borrowedUsd` are zero. + +--- + +## Prepare Endpoints (use web_request → send_calls) + +Verbs: `supply`, `withdraw`, `borrow`, `repay`. + +**GET form** (query params): + +``` +GET https://api.moonwell.fi/v1/prepare/supply?chain=base&asset=USDC&amountDecimal=100&from=
+``` + +**POST form** (JSON body — pass as the `body` object parameter to `web_request`): + +```json +{ + "url": "https://api.moonwell.fi/v1/prepare/supply", + "method": "POST", + "headers": { "content-type": "application/json" }, + "body": { "chain": "base", "asset": "USDC", "amountDecimal": "100", "from": "
" } +} +``` + +Both return identical response shapes. Use GET when simpler; use POST when the body is complex. + +### Key parameters + +| Field | Notes | +|-------|-------| +| `chain` | `base` (default), `optimism`, or chain ID | +| `asset` | Symbol: `USDC`, `WETH`, `ETH` (alias for WETH) | +| `amountDecimal` | Human-readable string, e.g. `"100"`. Use this **or** `amount` (base units), never both. | +| `from` | User's wallet address (from `get_wallets`) | + +### Response → send_calls mapping + +```json +{ + "data": { + "transactions": [ + { "step": "approve", "to": "0x...", "data": "0x...", "value": "0x0", "chainId": 8453 }, + { "step": "enter-market", "to": "0x...", "data": "0x...", "value": "0x0", "chainId": 8453 }, + { "step": "moonwell-supply", "to": "0x...", "data": "0x...", "value": "0x0", "chainId": 8453 } + ] + } +} +``` + +Pass all items as the `calls` array to `send_calls`, using `chainId` from any transaction item (`0x2105` for Base mainnet). + +--- + +## Example Flows + +### Supply 100 USDC on Base + +``` +1. get_wallets → address +2. web_request GET /token-balance/
?chain=base&asset=USDC → confirm balance ≥ 100 +3. web_request GET /prepare/supply?chain=base&asset=USDC&amountDecimal=100&from=
+4. send_calls(chainId=0x2105, calls from transactions[]) +5. User approves → get_request_status(requestId) +``` + +### Borrow USDC against collateral + +``` +1. get_wallets → address +2. web_request GET /health/
?chain=base → verify health > 1.5 +3. web_request GET /prepare/borrow?chain=base&asset=USDC&amountDecimal=50&from=
+4. send_calls(chainId=0x2105, calls from transactions[]) +5. User approves → get_request_status(requestId) +``` + +### Check positions and health + +``` +1. get_wallets → address +2. web_request GET /positions/
?chain=base&active=true → show per-market balances +3. web_request GET /health/
?chain=base → show health factor +``` + +--- + +## Protocol Notes + +- **mTokens** — ERC-20 receipt tokens (mUSDC, mWETH…); exchange rate accrues over time +- **WETH special-case** — borrow/withdraw deliver native ETH; supply/repay require ERC-20 WETH. Both `asset=ETH` and `asset=WETH` resolve to the same mWETH market +- **Compound v2 error codes** — `mint`, `borrow`, `repay` return non-zero codes for business-logic failures without reverting. Check the onchain receipt after broadcast +- **Base has two mUSDC entries** — the current market and a deprecated bridged-USDC market. Disambiguate by `marketAddress` or `deprecated: true` + +### Health factor guide + +| Value | Status | +|-------|--------| +| `> 1.5` | Healthy | +| `1.1 – 1.5` | Caution | +| `< 1.1` | Liquidation risk | +| `null` | No borrows | + +--- + +## Chain IDs for send_calls + +| Chain | chainId param | +|-------|--------------| +| Base mainnet | `0x2105` | +| Optimism | `0xa` | diff --git a/docs/ai-agents/skills/plugins/morpho.md b/docs/ai-agents/skills/plugins/morpho.md new file mode 100644 index 000000000..d4e6e0285 --- /dev/null +++ b/docs/ai-agents/skills/plugins/morpho.md @@ -0,0 +1,72 @@ +--- +title: "Morpho Plugin" +description: "Skill plugin reference for lending on Morpho through Base MCP." +--- + +# Morpho Plugin + +> [!IMPORTANT] +> Complete the short Base MCP onboarding flow defined in `SKILL.md` before calling any Morpho tool — the user's wallet address (required by Morpho write/position calls) is fetched lazily, and the disclaimer must be shown once per session. + +Morpho is a lending protocol on Base. The Morpho MCP server prepares lending operations (deposit, borrow, withdraw, repay, supply collateral) and returns unsigned calldata that is then executed via Base MCP's batched-calls tool. + +The exact list of Morpho tools, their parameters, and supported chains are exposed by the Morpho MCP itself — read its tool descriptions rather than relying on a fixed catalog in this file. Tools may be added, renamed, or removed over time. + +## MCP Server + +URL: `https://mcp.morpho.org/` + +## Installation (alongside Base MCP) + +```json +{ + "mcpServers": { + "base-account": { "url": "https://mcp.base.org" }, + "morpho": { "url": "https://mcp.morpho.org/" } + } +} +``` + +Claude Code: `claude mcp add morpho --transport http https://mcp.morpho.org/` + +## Orchestration Pattern + +Morpho's prepare-style tools (deposit, withdraw, supply, borrow, repay, supply/withdraw collateral) return an unsigned `calls` array plus a `chainId`. Pass them straight to Base MCP's batched-calls tool. + +``` +morpho prepare tool → { calls: [...], chainId } + ↓ +batched-calls tool (chainId, calls) → approval URL + request ID + ↓ user approves +status-poll tool (request ID) → confirmed +``` + +See [../references/batch-calls.md](../references/batch-calls.md) and [../references/approval-mode.md](../references/approval-mode.md). + +## Example Prompts + +``` +Find the best USDC vault on Base by APY and deposit 100 USDC +``` +1. Query Morpho vaults filtered by USDC, sorted by APY. +2. Call the Morpho prepare-deposit tool for the chosen vault and amount. +3. Pass the returned `calls` + `chainId` to Base MCP's batched-calls tool. +4. Hand the user the approval link; once they confirm, poll the request status. + +``` +Show all my Morpho positions on Base +``` +1. Fetch the user's address (if not already known). +2. Call the Morpho positions tool with that address. + +``` +Check if my Morpho borrow position is healthy +``` +1. Fetch the user's address. +2. Call the Morpho positions tool and report the health factor from the response. + +## Important Notes + +- Morpho's prepare tools typically simulate before returning — review simulation output before submitting the batch. +- Use the Morpho simulation tool for novel or large operations. +- Always check the supported-chains tool for the current list rather than assuming a fixed set. diff --git a/docs/ai-agents/skills/plugins/uniswap.md b/docs/ai-agents/skills/plugins/uniswap.md new file mode 100644 index 000000000..625e8ced2 --- /dev/null +++ b/docs/ai-agents/skills/plugins/uniswap.md @@ -0,0 +1,470 @@ +--- +title: "Uniswap Plugin" +description: "Skill plugin reference for swapping and LPing on Uniswap through Base MCP." +--- + +# Uniswap Plugin + +> [!IMPORTANT] +> Complete the short Base MCP onboarding flow defined in `SKILL.md` before calling any Uniswap endpoint. The user's wallet address — passed as `walletAddress` in every swap and LP call — is fetched lazily when needed. + +Uniswap on Base: token swaps using the proxy-approval flow (no Permit2 signing) and LP position management for V2, V3, and V4. Use `web_request` to fetch unsigned calldata from the Uniswap API, then execute transaction previews with `send_calls`. + +No additional MCP server is required. + +**Prerequisite:** `trade-api.gateway.uniswap.org` and `liquidity.api.uniswap.org` must be in the MCP server's `web_request` allowlist. If requests are rejected by the allowlist, inform the user. + +**Chain:** Base mainnet (chainId `8453` / `0x2105`) + +--- + +## Auth Headers + +Use these headers for all requests: + +```json +{ + "Content-Type": "application/json", + "x-api-key": "NeoYO3V50_koJAipDEalYWbMO1XMaFPAQmpOm6_Npo0" +} +``` + +For the swap proxy-approval flow, also include this header on **all** swap endpoints: `/check_approval`, `/quote`, and `/swap`. + +```json +{ + "x-permit2-disabled": "true" +} +``` + +Without `x-permit2-disabled`, Uniswap can return Permit2 or Universal Router behavior instead of the proxy-approval flow described here. + +--- + +## Swap Flow: Proxy Approval, No Permit2 + +Base URL: `https://trade-api.gateway.uniswap.org/v1` + +```text +POST /check_approval -> if approval non-null, include approval calldata in send_calls +POST /quote -> get best route, read-only +POST /swap -> get unsigned swap tx, include swap calldata in send_calls +``` + +### 1. `POST /check_approval` + +Headers: auth headers plus `"x-permit2-disabled": "true"`. + +```json +{ + "walletAddress": "
", + "token": "", + "amount": "", + "chainId": 8453, + "includeGasInfo": true +} +``` + +Response: + +```json +{ + "approval": { + "to": "", + "data": "", + "value": "0x00", + "chainId": 8453 + } +} +``` + +`approval` can be `null`, especially for native ETH. If it is non-null, pass it to `send_calls`. You can batch the approval and swap together after `/swap` returns. + +### 2. `POST /quote` + +Headers: auth headers plus `"x-permit2-disabled": "true"`. + +```json +{ + "type": "EXACT_INPUT", + "amount": "", + "tokenIn": "
", + "tokenOut": "
", + "tokenInChainId": 8453, + "tokenOutChainId": 8453, + "swapper": "
", + "autoSlippage": "DEFAULT", + "protocols": ["V4", "V3", "V2"], + "routingPreference": "BEST_PRICE" +} +``` + +Use `"slippageTolerance": <0-20>` instead of `autoSlippage` if the user specifies slippage. See [Slippage Warnings](#slippage-warnings) before submitting elevated values. + +Response includes a top-level `quote` object plus metadata. Keep the response as a flat object for `/swap`; do not nest it under a `quote` key. + +### 3. `POST /swap` + +Headers: auth headers plus `"x-permit2-disabled": "true"`. + +Use the `/quote` response as the body, but remove any null or absent permit fields before sending: + +```js +const swapBody = { ...quoteResponse }; +if (swapBody.permitData == null) delete swapBody.permitData; +if (swapBody.permitTransaction == null) delete swapBody.permitTransaction; +delete swapBody.signature; +``` + +Do not send `signature`, and do not send `permitData` or `permitTransaction` when they are `null`. + +Response: + +```json +{ + "swap": { + "to": "", + "data": "", + "value": "0x00", + "chainId": 8453 + }, + "gasFee": "..." +} +``` + +### Swap `send_calls` + +Approval and swap can be sent separately or batched in one `send_calls` preview: + +```json +{ + "chain": "base", + "calls": [ + { "to": "", "value": "", "data": "" }, + { "to": "", "value": "", "data": "" } + ] +} +``` + +### Swap Orchestration + +```text +1. get_wallets -> address; convert tokenIn amount to base units +2. web_request POST /check_approval with x-permit2-disabled +3. web_request POST /quote with x-permit2-disabled +4. Build swapBody from quoteResponse and remove null permit fields +5. web_request POST /swap with x-permit2-disabled +6. send_calls("base", approval + swap calls if approval exists, otherwise swap only) +7. Open the approvalUrl if requested; do not approve unless the user explicitly asks +8. get_request_status only after the user acts +``` + +--- + +## LP Flow + +Base URL: `https://liquidity.api.uniswap.org/lp` + +Use this host for LP endpoints in this plugin environment. Do not switch to `api.uniswap.org` or `trade-api.gateway.uniswap.org/v1/lp/...` unless that host is explicitly available to the API key and MCP allowlist. + +### Pool Discovery: `POST /lp/pool_info` + +Use pool discovery before creating V3/V4 LP positions. `poolReference` must be a valid pool address for V3 or pool ID for V4. + +```json +{ + "protocol": "V4", + "chainId": 8453, + "poolParameters": { + "tokenAddressA": "0x0000000000000000000000000000000000000000", + "tokenAddressB": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "fee": 3000, + "tickSpacing": 60 + } +} +``` + +Known Base V4 ETH/USDC `fee=3000`, `tickSpacing=60` pool reference observed in testing: + +```text +0xe070797535b13431808f8fc81fdbe7b41362960ed0b55bc2b6117c49c51b7eb9 +``` + +Pool references can change by pair, fee, tick spacing, and protocol. Prefer querying `/lp/pool_info` instead of hard-coding a pool reference unless the user explicitly selected a pool. + +### Approval Step: `POST /lp/check_approval` + +Use this before LP create/increase/decrease operations. The body uses `lpTokens` as an array of token/amount objects. + +```json +{ + "protocol": "V4", + "walletAddress": "
", + "chainId": 8453, + "lpTokens": [ + { + "tokenAddress": "0x0000000000000000000000000000000000000000", + "amount": "" + }, + { + "tokenAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "amount": "" + } + ], + "action": "CREATE", + "generatePermitAsTransaction": true, + "simulateTransaction": true +} +``` + +`action`: `"CREATE"` | `"INCREASE"` | `"DECREASE"` | `"MIGRATE"` + +Response: + +```json +{ + "requestId": "...", + "transactions": [ + { + "transaction": { + "to": "...", + "from": "...", + "data": "...", + "value": "0x00", + "chainId": 8453 + }, + "cancelApproval": false, + "action": "CREATE" + } + ] +} +``` + +If `transactions` is empty, no approval transaction is needed. If it has entries, map every `transactions[*].transaction` to `send_calls`. + +```js +const approvalCalls = approvalResponse.transactions.map((entry) => ({ + to: entry.transaction.to, + value: entry.transaction.value ?? "0x0", + data: entry.transaction.data +})); +``` + +### Create V3/V4 Position: `POST /lp/create` + +```json +{ + "walletAddress": "
", + "chainId": 8453, + "protocol": "V4", + "existingPool": { + "token0Address": "0x0000000000000000000000000000000000000000", + "token1Address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "poolReference": "0xe070797535b13431808f8fc81fdbe7b41362960ed0b55bc2b6117c49c51b7eb9" + }, + "independentToken": { + "tokenAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "amount": "1000000" + }, + "tickBounds": { + "tickLower": -200400, + "tickUpper": -199200 + }, + "simulateTransaction": false, + "nativeTokenBalance": "1000000000000000" +} +``` + +Use `newPool` instead of `existingPool` when creating a pool: + +```json +{ + "token0Address": "
", + "token1Address": "
", + "fee": 3000, + "tickSpacing": 60, + "initialPrice": "" +} +``` + +Response: + +```json +{ + "create": { "to": "...", "data": "...", "value": "...", "chainId": 8453 }, + "token0": { "tokenAddress": "...", "amount": "..." }, + "token1": { "tokenAddress": "...", "amount": "..." }, + "adjustedMinPrice": "...", + "adjustedMaxPrice": "...", + "tickLower": -200400, + "tickUpper": -199200 +} +``` + +Prefer `tickBounds` when possible. `priceBounds` can be accepted by the API, but its price units are easy to misread; validate carefully before using it. + +### Manage Existing Positions + +| Action | Endpoint | Key params | +| --- | --- | --- | +| Add liquidity | `POST /lp/increase` | `walletAddress`, `chainId`, `protocol`, `token0Address`, `token1Address`, `nftTokenId`, `independentToken { tokenAddress, amount }` | +| Remove liquidity | `POST /lp/decrease` | `walletAddress`, `chainId`, `protocol`, `token0Address`, `token1Address`, `nftTokenId`, `liquidityPercentageToDecrease` (0-100) | +| Collect fees | `POST /lp/claim_fees` | `walletAddress`, `chainId`, `protocol`, `tokenId`; optional `simulateTransaction` | +| Create V2 position | `POST /lp/create_classic` | `walletAddress`, `poolParameters { token0Address, token1Address, chainId }`, `independentToken { tokenAddress, amount }` | + +Optional on LP operation endpoints: `"slippageTolerance": ` where `0.5` means 0.5%. See [Slippage Warnings](#slippage-warnings) before submitting elevated values. + +Important: LP APIs can return calldata for syntactically valid `nftTokenId` values even if the connected wallet may not own the position. Treat generated calldata as a transaction preview input, not proof of ownership or guaranteed execution. + +### Claim Fees: `POST /lp/claim_fees` + +```json +{ + "protocol": "V4", + "walletAddress": "
", + "chainId": 8453, + "tokenId": "", + "simulateTransaction": false +} +``` + +Response: + +```json +{ + "claim": { "to": "...", "data": "...", "value": "0x00", "chainId": 8453 }, + "token0": { "tokenAddress": "...", "amount": "..." }, + "token1": { "tokenAddress": "...", "amount": "..." } +} +``` + +No approval step is needed for fee collection. + +### Create V2 Position: `POST /lp/create_classic` + +```json +{ + "walletAddress": "
", + "poolParameters": { + "token0Address": "0x4200000000000000000000000000000000000006", + "token1Address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "chainId": 8453 + }, + "independentToken": { + "tokenAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "amount": "1000000" + }, + "simulateTransaction": false +} +``` + +For V2 create, `/lp/check_approval` may return multiple approval transactions. Batch all approvals plus the `create` transaction if you want one `send_calls` approval link. + +### LP `send_calls` + +For any LP operation response field such as `create`, `increase`, `decrease`, or `claim`, map to: + +```json +{ + "chain": "base", + "calls": [ + { "to": "", "value": "", "data": "" } + ] +} +``` + +For approval + action batching: + +```js +const operationTx = + operationResponse.create ?? + operationResponse.increase ?? + operationResponse.decrease ?? + operationResponse.claim; + +const calls = [ + ...approvalResponse.transactions.map((entry) => ({ + to: entry.transaction.to, + value: entry.transaction.value ?? "0x0", + data: entry.transaction.data + })), + { + to: operationTx.to, + value: operationTx.value ?? "0x0", + data: operationTx.data + } +]; +``` + +### LP Orchestration + +```text +1. get_wallets -> address +2. For V3/V4 create, call /lp/pool_info to discover poolReference +3. Build LP token amount list in base units +4. web_request POST /lp/check_approval +5. web_request POST /lp/create, /lp/increase, /lp/decrease, /lp/claim_fees, or /lp/create_classic +6. send_calls("base", approval calls + operation call) +7. Open the approvalUrl if requested; do not approve unless the user explicitly asks +8. get_request_status only after the user acts +``` + +--- + +## Example Prompts + +**Swap 1 USDC to WETH on Base** +1. `get_wallets` -> address; use USDC address `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`, amount `1000000`. +2. `web_request POST /check_approval` with `x-permit2-disabled: true`. +3. `web_request POST /quote` with `x-permit2-disabled: true`. +4. Remove null permit fields from quote response. +5. `web_request POST /swap` with `x-permit2-disabled: true`. +6. `send_calls` approval + swap, or swap only if no approval was returned. + +**Create a V4 ETH/USDC LP position on Base** +1. `get_wallets` -> address. +2. `web_request POST /lp/pool_info` to find the pool reference. +3. `web_request POST /lp/check_approval` using `lpTokens` array. +4. `web_request POST /lp/create` using `existingPool.poolReference` and `tickBounds`. +5. `send_calls` approval transactions plus create transaction. + +**Add liquidity to an existing V4 position** +1. `get_wallets` -> address. +2. Confirm the wallet owns the `nftTokenId` or warn that generated calldata may still fail. +3. `web_request POST /lp/check_approval` with action `"INCREASE"`. +4. `web_request POST /lp/increase`. +5. `send_calls` approval transactions plus increase transaction. + +**Collect LP fees** +1. `get_wallets` -> address. +2. `web_request POST /lp/claim_fees` with `tokenId`. +3. `send_calls` claim transaction. + +--- + +## Slippage Warnings + +High slippage tolerance exposes the user to worse fills and sandwich/MEV attacks. Before calling `/swap` or any LP endpoint with an elevated value, warn the user and get explicit confirmation: + +| Tolerance | Level | Action | +| --- | --- | --- | +| ≤ 1% | Normal | Proceed. | +| > 1% and ≤ 5% | Elevated | Mention the value and ask the user to confirm. | +| > 5% and ≤ 20% | High | Warn that the trade can fill significantly below quote and is a likely sandwich target. Require explicit confirmation. | +| > 20% | Very high | Strongly warn; do not submit without the user re-confirming the exact number. | + +Apply the same thresholds to swap and LP slippage. If the user did not specify a value, prefer `autoSlippage: "DEFAULT"` on swaps rather than picking a high number. + +--- + +## Notes + +- Native ETH address: `0x0000000000000000000000000000000000000000` +- USDC on Base: `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` +- WETH on Base: `0x4200000000000000000000000000000000000006` +- Token amounts are base units: USDC = 1e6 per token, ETH/WETH = 1e18 per token. +- Use `chain: "base"` with `send_calls`, not numeric chain id. +- For swap proxy approval, include `x-permit2-disabled: true` on `/check_approval`, `/quote`, and `/swap`. +- For swap proxy approval, remove null `permitData` and `permitTransaction` fields before calling `/swap`. +- `/quote` response fields must be spread directly into `/swap` body, not nested under a `quote` key. +- Do not send `signature` in the proxy swap flow. diff --git a/docs/ai-agents/skills/references/approval-mode.md b/docs/ai-agents/skills/references/approval-mode.md new file mode 100644 index 000000000..1048236b3 --- /dev/null +++ b/docs/ai-agents/skills/references/approval-mode.md @@ -0,0 +1,29 @@ +--- +title: "Approval Mode" +description: "Skill reference for how Base MCP returns approval URLs and request IDs for every write call." +--- + +> Today the Base MCP exposes a single execution mode for write tools: **approval mode** (the user manually approves each transaction via a returned URL). Other modes may be added later. Treat the tool descriptions exposed by the MCP as the source of truth — if a future write tool returns a different shape or skips the approval step, follow what the MCP describes, not this file. + +# Approval Mode + +In approval mode, every write call (send, swap, sign, batched calls, and any plugin-prepared transaction routed through Base MCP) returns an **approval URL** plus a **request ID**. The user opens the URL, approves the transaction in their wallet UI, and then the agent polls the request ID for completion. + +## Flow + +1. **Call the write tool.** The response includes: + - an approval URL (the field name is on the MCP response — typically `approvalUrl`) + - a request ID (typically `requestId`) +2. **Show the user the link.** Present it as **"Approve Transaction"** (or similar neutral language). Do not name or describe the wallet provider behind the link, even when the URL hostname suggests one — the underlying wallet UI is an implementation detail and may change. Just give the user the link to click. + - Beginner-friendly phrasing: _"Open this to approve the transaction: [Approve Transaction]()"_ + - Terse phrasing: _"[Approve Transaction]()"_ +3. **Wait for the user to confirm they approved.** Don't poll in a tight loop while they're still acting. +4. **Call the status-poll tool** (typically `get_request_status`) with the request ID once. +5. **Only report success** when the status tool confirms completion. + +## Common mistakes + +- Reporting success before the status tool confirms it — the user may not have approved yet. +- Skipping the approval link — the transaction cannot complete without user action. +- Naming the wallet/approval provider, or surfacing the raw hostname as the link text — say "Approve Transaction". +- Polling the status tool in a tight loop instead of once after the user confirms. diff --git a/docs/ai-agents/skills/references/batch-calls.md b/docs/ai-agents/skills/references/batch-calls.md new file mode 100644 index 000000000..a65ebaa84 --- /dev/null +++ b/docs/ai-agents/skills/references/batch-calls.md @@ -0,0 +1,40 @@ +--- +title: "Batched Contract Calls" +description: "Skill reference for Base MCP's EIP-5792 batched contract calls." +--- + +# Batched Contract Calls (EIP-5792) + +Base MCP exposes a batched-calls tool (typically `send_calls`) that submits multiple EIP-5792 `wallet_sendCalls` for a single user approval. Use it for arbitrary contract interactions, multi-step transactions, or any flow that combines an approval with a follow-up action. + +> **Batching is preferred whenever a flow involves a token approval followed by a protocol action** (approve + deposit, approve + supply, approve + swap, etc.). Also batch whenever a plugin or protocol endpoint returns multiple transactions in a single response. Don't split these into sequential single-`send` calls when one batched approval can execute them atomically. + +## When to use + +- Protocol interactions not covered by `send` or `swap` (DeFi, NFT mints, approvals, governance actions). +- Combining multiple operations into one user approval. +- Executing a transaction array returned by a plugin's prepare-style endpoint — pass the array straight through. + +## Shape + +The MCP advertises the exact parameter names and types — defer to its tool description. The general shape is: + +- A `chainId` (hex with `0x` prefix — `0x2105` for Base mainnet, `0x14a34` for Base Sepolia). +- A `calls` array of `{ to, value, data }` objects: + - `to` — target address, `0x`-prefixed (required) + - `value` — hex ETH in wei (e.g. `0x0`), optional + - `data` — calldata hex, optional + +## Approval flow + +Same as any write tool: the response returns an approval URL and request ID. See [approval-mode.md](approval-mode.md). + +## Generic orchestration + +``` +plugin or protocol API → { transactions: [...] } (or equivalent) + ↓ map each transaction to a { to, value, data } call +batched-calls tool (chainId, calls) → approval URL + request ID + ↓ user approves +status-poll tool (request ID) → confirmed +``` diff --git a/docs/ai-agents/skills/references/custom-plugins.md b/docs/ai-agents/skills/references/custom-plugins.md new file mode 100644 index 000000000..38f5aa113 --- /dev/null +++ b/docs/ai-agents/skills/references/custom-plugins.md @@ -0,0 +1,49 @@ +--- +title: "Custom Plugins and the web_request Allowlist" +description: "Skill reference for how Base MCP routes plugin HTTP calls and which surfaces are allowlisted." +--- + +# Custom / Non-Native Plugins and the `web_request` Allowlist + +The native plugins shipped with this skill (Morpho, Moonwell, Uniswap, Avantis) have their HTTP APIs **allowlisted in the Base MCP `web_request` tool**. This matters because Claude and ChatGPT restrict which APIs an agent can call directly from their surface — `web_request` is what makes those calls possible. + +Custom or user-supplied plugins (anything outside the four native ones) are almost certainly **not** in the allowlist and will be rejected by `web_request`. + +## Priority order for HTTP calls + +Use this order **for every plugin call — native or not**: + +### 1. Harness HTTP tool (preferred whenever available) + +If the current environment lets you call HTTP APIs directly — e.g. Claude Code, Codex, Cursor, or any harness where you have a fetch / curl / shell tool — **use that tool first**, even for native plugins. It supports any HTTP method (GET, POST, etc.), avoids the allowlist entirely, and gives you the full response without round-tripping through the MCP. + +Only fall back to `web_request` if you don't have a usable HTTP tool in the current harness. + +### 2. `web_request` (when no harness HTTP tool exists) + +If the harness has no direct HTTP capability, route the call through Base MCP's `web_request`: + +- **Native plugin host** — works out of the box (the host is allowlisted). +- **Non-native plugin host** — will be rejected. Do not silently retry. Move to path 3. + +### 3. User-paste fallback (Claude / ChatGPT consumer surfaces, non-native hosts) + +Claude and ChatGPT *can* fetch GET URLs themselves, but for security reasons they will only fetch URLs that the **user has pasted into the chat**. The agent cannot freely construct and fetch arbitrary URLs on its own. + +That makes the fallback effectively **GET-only**: there's no equivalent escape hatch for POST/PUT/DELETE with custom headers and a body, because the user can't realistically inject those into the chat in a fetchable form. + +So for non-native plugins on Claude / ChatGPT consumer surfaces: + +- **Only GET-style APIs are viable.** If the protocol's API requires POST or other write methods to retrieve calldata, surface this limitation to the user — explain that their environment can't perform the fetch and that they would need a harness with HTTP tools (e.g. Claude Code) to proceed. +- For GET endpoints: + 1. Construct the full URL with every query parameter encoded inline (address, amount, slippage, chain, etc.). + 2. Show the URL to the user and ask them to paste it back into the chat. Once pasted, you can fetch it yourself — that's the security model these surfaces enforce. + 3. Parse the response and continue the flow (e.g. map returned calldata into the batched-calls tool, then walk through the approval flow — see [approval-mode.md](approval-mode.md) and [batch-calls.md](batch-calls.md)). + +## Decision summary + +| Situation | What to do | +|-----------|------------| +| Any plugin, harness has an HTTP tool (Claude Code, Codex, Cursor, …) | **Use the harness's HTTP tool first.** Any method is fine. Don't route through `web_request` when a direct call is available. | +| Native plugin, no harness HTTP tool | Use `web_request` — the host is allowlisted. | +| Non-native plugin, no harness HTTP tool (Claude / ChatGPT consumer apps) | GET only. Construct the URL, ask the user to paste it into the chat so you're allowed to fetch it, then parse the response. If the API needs POST, tell the user this surface can't support it. | diff --git a/docs/ai-agents/skills/references/install.md b/docs/ai-agents/skills/references/install.md new file mode 100644 index 000000000..474b5e583 --- /dev/null +++ b/docs/ai-agents/skills/references/install.md @@ -0,0 +1,159 @@ +--- +title: "Installing Base MCP" +description: "Skill reference for installing the Base MCP server in Claude, ChatGPT, Cursor, Codex, and other surfaces." +--- + +# Installing Base MCP + +> Canonical source: ****. That page is kept up to date with the latest one-click install links, deep-links, and connector flows for each surface. Send the user there first; the instructions below are a backup so the agent can still walk a user through install without leaving the chat. + +The MCP server URL is the same everywhere: **`https://mcp.base.org`** + +--- + +## Claude (Claude.ai web, Claude Desktop, iOS, Android) + +One-click add: + +``` +https://claude.ai/customize/connectors?modal=add-custom-connector&connectorName=Base&connectorUrl=https%3A%2F%2Fmcp.base.org +``` + +Or manually: + +1. Open **Customize → Connectors → Add custom connector** +2. Fill in: + - **Name**: `Base` + - **Remote MCP server URL**: `https://mcp.base.org` +3. Click **Add** + +A browser tab opens to authorize on first use — sign in with Base. + +--- + +## ChatGPT + +Open (or **Settings → Connectors**), then: + +1. Enable **Developer Mode** if prompted (under Advanced) +2. Click **Create** → **New App** modal opens +3. Fill in: + - **Name**: `Base` + - **Description** (optional): `Wallet and onchain tools for Base` + - **MCP Server URL**: `https://mcp.base.org` + - **Authentication**: `OAuth` +4. Check **I understand and want to continue** on the risk warning +5. Click **Create** + +ChatGPT prompts for authorization the first time a wallet tool is called. + +--- + +## Claude Code + +Add to the current project: + +```bash +claude mcp add --transport http base https://mcp.base.org +``` + +Install globally across all projects: + +```bash +claude mcp add --transport http --scope user base https://mcp.base.org +``` + +Verify: + +```bash +claude mcp list +``` + +The `base` server shows with a tool count once active. Inside a session, `/mcp` also shows server status. + +--- + +## Codex + +```bash +codex mcp add base --url https://mcp.base.org/ +``` + +Or in `codex.toml`: + +```toml +[mcp_servers.base] +url = "https://mcp.base.org/" +``` + +--- + +## Cursor + +Deep link install: + +``` +cursor://anysphere.cursor-deeplink/mcp/install?name=base&config=eyJ1cmwiOiJodHRwczovL21jcC5iYXNlLm9yZyJ9 +``` + +Or manually in `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project): + +```json +{ + "mcpServers": { + "base": { + "url": "https://mcp.base.org" + } + } +} +``` + +Restart Cursor, then **Settings → MCP** to confirm `base` is active. + +--- + +## Hermes + +Hand the agent the quickstart and let it install itself: + +``` +Install the Base MCP server from https://docs.base.org/ai-agents/quickstart +``` + +Manual install — edit `~/.hermes/config.yaml`: + +```yaml +mcp_servers: + base: + url: "https://mcp.base.org" +``` + +Then start a new chat (or `/reload-mcp` in an existing one). + +--- + +## Authorization (first use) + +The first time a wallet tool is called, an auth modal opens for the user to authorize the Base Account. Click **Allow** once. (See the live demo on the quickstart page.) After that, write operations still require per-transaction approval — see [approval-mode.md](approval-mode.md). + +--- + +## Did it work? + +Ask the assistant: + +> Show me my wallets + +If it replies with a wallet address, the MCP is connected. If it says it doesn't have wallet tools, the MCP isn't loaded — retry the install steps or fall back to the quickstart link. + +--- + +## Troubleshooting + +| Symptom | Try | +|---------|-----| +| No browser tab for sign-in | Open `https://mcp.base.org` directly, sign in, then re-add the server. | +| "Integration not found" / "Tool not available" | Restart the app — the server may not have finished loading. | +| Integrations / Connectors tab missing | App version is too old — update to the latest. | +| `web_request` rejects a hostname | The hostname isn't in the allowlist. For native plugins, this shouldn't happen; for custom plugins see [custom-plugins.md](custom-plugins.md). | +| Anything else | Send the user to . | diff --git a/docs/ai-agents/skills/references/tone.md b/docs/ai-agents/skills/references/tone.md new file mode 100644 index 000000000..a3a9c5a86 --- /dev/null +++ b/docs/ai-agents/skills/references/tone.md @@ -0,0 +1,49 @@ +--- +title: "Tone" +description: "Skill reference for the language and tone rules an agent should follow when using Base MCP." +--- + +# Tone + +These rules apply for the entire conversation. Load this file at session start. + +## Language rules (always enforced) + +- Write **onchain** — never "on-chain" or "on chain" +- Never use the word **web3** +- Never say "on-chain" in any form + +## Detecting user sophistication + +Infer from available signals — do not ask the user directly. + +**Sophisticated user signals:** +- Harness is Claude Code, Cursor, or a direct API/SDK integration +- User pastes raw addresses, calldata, or hex values +- User uses precise protocol terminology (e.g. "health factor", "calldata", "EIP-712", "send_calls") + +**Beginner user signals:** +- Harness is Claude.ai app or ChatGPT desktop/web +- User asks "how do I", "what is", "can you help me" +- No address or technical data pasted; plain conversational language + +## Stating the assumed level + +At the start of the first substantive response, briefly state the assumed level so the user can correct it if wrong: + +- Beginner assumed: *"I'll keep things straightforward — let me know if you want more technical detail."* +- Sophisticated assumed: state nothing; just proceed with terse, precise responses. + +## Beginner mode + +- Use plain terms: "your wallet address", "approve the transaction in your browser", "this may take a few seconds to confirm" +- Avoid raw hex, ABI references, and protocol jargon without a plain-English explanation alongside +- Explain approval steps in order: "First open this link, then come back and let me know when you've approved it" +- Use friendly formatting: short paragraphs, bullet points for steps + +## Sophisticated mode + +- Be terse and precise +- Skip hand-holding and step-by-step preamble +- Use parameter names and return field names directly (e.g. "`approvalUrl`", "`requestId`") +- Omit explanations the user clearly already knows diff --git a/docs/docs.json b/docs/docs.json index a5d6b3905..11965696c 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -700,7 +700,7 @@ { "group": "Native Plugins", "pages": [ - "ai-agents/plugins/native-plugins", + "ai-agents/plugins/native/index", "ai-agents/plugins/native/morpho", "ai-agents/plugins/native/moonwell", "ai-agents/plugins/native/uniswap", From 664ec22d2ea8efd597ecf6bd4f7f0ed1c44a21b0 Mon Sep 17 00:00:00 2001 From: Youssef Date: Thu, 21 May 2026 19:46:21 +0100 Subject: [PATCH 35/36] update skill file --- docs/ai-agents/plugins/index.mdx | 12 +++---- docs/ai-agents/plugins/native/index.mdx | 2 +- docs/ai-agents/quickstart.mdx | 40 +++++++++------------ docs/ai-agents/skills/SKILL.md | 46 ++++++++++++------------- 4 files changed, 46 insertions(+), 54 deletions(-) diff --git a/docs/ai-agents/plugins/index.mdx b/docs/ai-agents/plugins/index.mdx index c8fb71fcb..89a71cf21 100644 --- a/docs/ai-agents/plugins/index.mdx +++ b/docs/ai-agents/plugins/index.mdx @@ -19,19 +19,19 @@ The MCP server exposes capabilities. Without context, models misuse them — cal ## How SKILL.md is loaded -Skills use progressive disclosure. The model loads `SKILL.md` at session start (cheap — ~100 lines) and reads `references/*.md` and `plugins/*.md` only when a relevant task arises. +Skills use progressive disclosure. The model loads `SKILL.md` at session start (cheap — ~100 lines) and fetches reference and plugin files on demand only when a relevant task arises. Each reference and plugin is a standalone markdown file hosted at a stable `docs.base.org` URL; the model pulls them in with `web_request`. -The shape of the Base MCP skill: +The skill itself is just one file. The references and plugins it points at live in the Base docs: - - + + - + @@ -42,7 +42,7 @@ The shape of the Base MCP skill: -`SKILL.md` itself defines the session flow: **Detection → Tone → Onboarding → Tools table → Plugins table**. When the user asks to swap tokens, the model pulls in `references/tools.md`. When they ask about a Morpho vault, the model pulls in `plugins/morpho.md`. Nothing else is in context. +`SKILL.md` itself defines the session flow: **Detection → Tone → Onboarding → Tools table → Plugins table**. When the user asks about batched calls, the model fetches `references/batch-calls.md`. When they ask about a Morpho vault, the model fetches `plugins/morpho.md`. Nothing else is in context. Read the canonical file at [`skills/base-mcp/SKILL.md`](https://github.com/base/skills/blob/main/skills/base-mcp/SKILL.md). diff --git a/docs/ai-agents/plugins/native/index.mdx b/docs/ai-agents/plugins/native/index.mdx index 9addf8f97..9f4d07869 100644 --- a/docs/ai-agents/plugins/native/index.mdx +++ b/docs/ai-agents/plugins/native/index.mdx @@ -28,7 +28,7 @@ All four follow the same prepare → `send_calls` contract described in the [Ove ## Using a native plugin - + Connect `mcp.base.org` and load the skill in your client. See the [Quickstart](/ai-agents/quickstart) for Claude, Claude Desktop, ChatGPT, Cursor, and Claude Code. diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index d0b4731d0..f7b79ccfd 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -126,47 +126,39 @@ import { AuthApprovalDemo } from "/snippets/AuthApprovalDemo.jsx" - - The `base-mcp` skill extends your assistant with pre-built prompts and workflows for wallet operations, token transfers, and DeFi interactions on Base. + + The `base-mcp` skill teaches your assistant the onboarding flow, wallet workflows, and where to fetch reference and plugin docs on demand. It's a single markdown file — no download, no install. Paste the prompt below into a new conversation and your assistant will fetch the skill and walk you through setup. - - Download for Claude - + **Option 1: Paste a prompt (any plan)** - Click the button above to download `base-mcp.zip`, then pick one: + Paste this into a new Claude conversation: - **Option 1: Drop the zip into a conversation** + + Fetch this Base MCP skill and follow it to onboard me — including any reference or plugin files it tells you to load: `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/SKILL.md` + - Attach the downloaded `base-mcp.zip` to a new Claude conversation and ask Claude to read the skill and onboard you. Quickest way to try it without changing any settings. + Claude will fetch the skill via web_request, verify the Base MCP connection from the previous step, and run the short onboarding flow defined in the skill. **Option 2: Install as a persistent skill** + Download the `base-mcp` skill folder from [`github.com/base/skills/tree/youssef/add-build-on-base-and-base-mcp/skills/base-mcp`](https://github.com/base/skills/tree/youssef/add-build-on-base-and-base-mcp/skills/base-mcp), then: + 1. In Claude Desktop or Claude.ai, open [**Customize → Skills**](https://claude.ai/customize/skills) - 2. Click **Upload skill** and select the downloaded `base-mcp.zip` + 2. Click **Upload skill** and select the downloaded skill 3. Toggle the skill on Claude activates the skill automatically when relevant to your prompt. See [Use skills in Claude](https://support.claude.com/en/articles/12512180-use-skills-in-claude) for details. - - Download for ChatGPT - - - Click the button above to download `base-mcp.zip`, then pick one: - - **Option 1: Drop the zip into a conversation** - - Attach the downloaded `base-mcp.zip` to a new ChatGPT conversation and ask ChatGPT to read the skill and onboard you. Works on any ChatGPT plan, the quickest way to try it without changing any settings. - - **Option 2: Install as a persistent skill (Business, Enterprise, Edu, Teachers, Healthcare plans)** + Paste this into a new ChatGPT conversation: - 1. In ChatGPT, open [**Settings → Skills**](https://chatgpt.com/skills) - 2. Click **Add skill** and upload the downloaded `base-mcp.zip` - 3. Enable the skill for the conversations where you want it active + + Fetch this Base MCP skill and follow it to onboard me — including any reference or plugin files it tells you to load: `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/SKILL.md` + - See [Skills in ChatGPT](https://help.openai.com/en/articles/20001066-skills-in-chatgpt) for details. + ChatGPT will fetch the skill via web_request, verify the Base MCP connection from the previous step, and run the short onboarding flow defined in the skill. Works on any ChatGPT plan. ```bash Terminal diff --git a/docs/ai-agents/skills/SKILL.md b/docs/ai-agents/skills/SKILL.md index acdfaae8f..f0794e318 100644 --- a/docs/ai-agents/skills/SKILL.md +++ b/docs/ai-agents/skills/SKILL.md @@ -2,7 +2,7 @@ title: "Base MCP Skill" description: "Base MCP — gives your AI assistant access to a Base account via the Base MCP server (mcp.base.org). Wallet, portfolio, sending, swapping, signing, batched contract calls, and transaction history on Base." name: base-mcp -version: 0.1.0 +version: 0.2.0 --- # Base MCP @@ -12,11 +12,17 @@ version: 0.1.0 > > Including conversations that jump straight to a plugin topic. Onboarding is short — see below. +## How this skill loads references and plugins + +This skill is intentionally lightweight. The detailed reference and plugin files are **not bundled** — fetch them on demand from the Base docs site using `web_request` (or the harness's HTTP tool, if available). Always fetch the URLs exactly as written below — they end in `.md` so you get clean markdown instead of rendered HTML. + +Only fetch a reference or plugin file the first time you need it in a session; once loaded, its contents are in your context. + ## Detection -The Base MCP exposes its tools to the harness when connected. If no Base MCP tool is callable, the MCP server is not installed: direct the user to https://docs.base.org/ai-agents/quickstart (or load [references/install.md](references/install.md) for app-specific steps) and stop. +The Base MCP exposes its tools to the harness when connected. If no Base MCP tool is callable, the MCP server is not installed: direct the user to `https://docs.base.org/ai-agents/quickstart` (or fetch `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/install.md` for app-specific steps) and stop. -If Base MCP tools are available, load [references/tone.md](references/tone.md) — its rules apply for the entire conversation — then continue to Onboarding. +If Base MCP tools are available, fetch `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/tone.md` — its rules apply for the entire conversation — then continue to Onboarding. ## Onboarding @@ -34,15 +40,15 @@ Keep it short. Do this once per session, before doing real work: The Base MCP advertises its own tool catalog to the harness. Read the tool descriptions exposed by the MCP — they are the source of truth and may change over time. Do not assume a fixed list; do not preload a tool catalog from this skill. -Two patterns deserve their own references because they span multiple tools: +Two patterns deserve their own references because they span multiple tools. Fetch each one only when you need it: -| Topic | Reference | +| Topic | Fetch from | |-------|-----------| -| Approval flow (for any write tool that returns an approval URL) | [references/approval-mode.md](references/approval-mode.md) | -| Batched contract calls (EIP-5792) | [references/batch-calls.md](references/batch-calls.md) | -| Custom / non-native plugins and the `web_request` allowlist | [references/custom-plugins.md](references/custom-plugins.md) | -| Platform install steps | [references/install.md](references/install.md) | -| Tone and language rules | [references/tone.md](references/tone.md) | +| Approval flow (for any write tool that returns an approval URL) | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/approval-mode.md` | +| Batched contract calls (EIP-5792) | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/batch-calls.md` | +| Custom / non-native plugins and the `web_request` allowlist | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/custom-plugins.md` | +| Platform install steps | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/install.md` | +| Tone and language rules | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/tone.md` | ## Plugins @@ -50,21 +56,15 @@ Plugins extend Base MCP with partner-specific functionality (lending, swaps, per Plugins currently maintained alongside this skill (the **native plugins**): -| Plugin | Reference | +| Plugin | Fetch from | |--------|-----------| -| Morpho | [plugins/morpho.md](plugins/morpho.md) | -| Moonwell | [plugins/moonwell.md](plugins/moonwell.md) | -| Uniswap | [plugins/uniswap.md](plugins/uniswap.md) | -| Avantis | [plugins/avantis.md](plugins/avantis.md) | +| Morpho | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/plugins/morpho.md` | +| Moonwell | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/plugins/moonwell.md` | +| Uniswap | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/plugins/uniswap.md` | +| Avantis | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/plugins/avantis.md` | -Load a plugin reference only when the user's request matches it. For a plugin's own tools, defer to the descriptions the plugin's MCP exposes — this skill does not duplicate them. +Fetch a plugin reference only when the user's request matches it. For a plugin's own tools, defer to the descriptions the plugin's MCP exposes — this skill does not duplicate them. ### Native plugins vs. custom / user-supplied plugins -Native plugins are allowlisted in the Base MCP `web_request` tool and work everywhere. Custom or user-supplied plugins usually aren't allowlisted — load [references/custom-plugins.md](references/custom-plugins.md) for the decision tree on which HTTP path to use (harness HTTP tool vs. user-paste fallback, and the GET-only constraint on Claude/ChatGPT consumer surfaces). - -## Installation - -```bash -npx skills add base/skills --skill base-mcp -``` +Native plugins are allowlisted in the Base MCP `web_request` tool and work everywhere. Custom or user-supplied plugins usually aren't allowlisted — fetch `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/custom-plugins.md` for the decision tree on which HTTP path to use (harness HTTP tool vs. user-paste fallback, and the GET-only constraint on Claude/ChatGPT consumer surfaces). From b3ec7dc1e8f8a159f78f931bee39f840893851bf Mon Sep 17 00:00:00 2001 From: Youssef Date: Thu, 21 May 2026 19:52:42 +0100 Subject: [PATCH 36/36] revert --- docs/ai-agents/plugins/index.mdx | 12 +++---- docs/ai-agents/plugins/native/index.mdx | 2 +- docs/ai-agents/quickstart.mdx | 40 ++++++++++++--------- docs/ai-agents/skills/SKILL.md | 46 ++++++++++++------------- 4 files changed, 54 insertions(+), 46 deletions(-) diff --git a/docs/ai-agents/plugins/index.mdx b/docs/ai-agents/plugins/index.mdx index 89a71cf21..c8fb71fcb 100644 --- a/docs/ai-agents/plugins/index.mdx +++ b/docs/ai-agents/plugins/index.mdx @@ -19,19 +19,19 @@ The MCP server exposes capabilities. Without context, models misuse them — cal ## How SKILL.md is loaded -Skills use progressive disclosure. The model loads `SKILL.md` at session start (cheap — ~100 lines) and fetches reference and plugin files on demand only when a relevant task arises. Each reference and plugin is a standalone markdown file hosted at a stable `docs.base.org` URL; the model pulls them in with `web_request`. +Skills use progressive disclosure. The model loads `SKILL.md` at session start (cheap — ~100 lines) and reads `references/*.md` and `plugins/*.md` only when a relevant task arises. -The skill itself is just one file. The references and plugins it points at live in the Base docs: +The shape of the Base MCP skill: - - + + + - @@ -42,7 +42,7 @@ The skill itself is just one file. The references and plugins it points at live -`SKILL.md` itself defines the session flow: **Detection → Tone → Onboarding → Tools table → Plugins table**. When the user asks about batched calls, the model fetches `references/batch-calls.md`. When they ask about a Morpho vault, the model fetches `plugins/morpho.md`. Nothing else is in context. +`SKILL.md` itself defines the session flow: **Detection → Tone → Onboarding → Tools table → Plugins table**. When the user asks to swap tokens, the model pulls in `references/tools.md`. When they ask about a Morpho vault, the model pulls in `plugins/morpho.md`. Nothing else is in context. Read the canonical file at [`skills/base-mcp/SKILL.md`](https://github.com/base/skills/blob/main/skills/base-mcp/SKILL.md). diff --git a/docs/ai-agents/plugins/native/index.mdx b/docs/ai-agents/plugins/native/index.mdx index 9f4d07869..9addf8f97 100644 --- a/docs/ai-agents/plugins/native/index.mdx +++ b/docs/ai-agents/plugins/native/index.mdx @@ -28,7 +28,7 @@ All four follow the same prepare → `send_calls` contract described in the [Ove ## Using a native plugin - + Connect `mcp.base.org` and load the skill in your client. See the [Quickstart](/ai-agents/quickstart) for Claude, Claude Desktop, ChatGPT, Cursor, and Claude Code. diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx index f7b79ccfd..d0b4731d0 100644 --- a/docs/ai-agents/quickstart.mdx +++ b/docs/ai-agents/quickstart.mdx @@ -126,39 +126,47 @@ import { AuthApprovalDemo } from "/snippets/AuthApprovalDemo.jsx" - - The `base-mcp` skill teaches your assistant the onboarding flow, wallet workflows, and where to fetch reference and plugin docs on demand. It's a single markdown file — no download, no install. Paste the prompt below into a new conversation and your assistant will fetch the skill and walk you through setup. + + The `base-mcp` skill extends your assistant with pre-built prompts and workflows for wallet operations, token transfers, and DeFi interactions on Base. - **Option 1: Paste a prompt (any plan)** + + Download for Claude + - Paste this into a new Claude conversation: + Click the button above to download `base-mcp.zip`, then pick one: - - Fetch this Base MCP skill and follow it to onboard me — including any reference or plugin files it tells you to load: `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/SKILL.md` - + **Option 1: Drop the zip into a conversation** - Claude will fetch the skill via web_request, verify the Base MCP connection from the previous step, and run the short onboarding flow defined in the skill. + Attach the downloaded `base-mcp.zip` to a new Claude conversation and ask Claude to read the skill and onboard you. Quickest way to try it without changing any settings. **Option 2: Install as a persistent skill** - Download the `base-mcp` skill folder from [`github.com/base/skills/tree/youssef/add-build-on-base-and-base-mcp/skills/base-mcp`](https://github.com/base/skills/tree/youssef/add-build-on-base-and-base-mcp/skills/base-mcp), then: - 1. In Claude Desktop or Claude.ai, open [**Customize → Skills**](https://claude.ai/customize/skills) - 2. Click **Upload skill** and select the downloaded skill + 2. Click **Upload skill** and select the downloaded `base-mcp.zip` 3. Toggle the skill on Claude activates the skill automatically when relevant to your prompt. See [Use skills in Claude](https://support.claude.com/en/articles/12512180-use-skills-in-claude) for details. - Paste this into a new ChatGPT conversation: + + Download for ChatGPT + + + Click the button above to download `base-mcp.zip`, then pick one: + + **Option 1: Drop the zip into a conversation** + + Attach the downloaded `base-mcp.zip` to a new ChatGPT conversation and ask ChatGPT to read the skill and onboard you. Works on any ChatGPT plan, the quickest way to try it without changing any settings. + + **Option 2: Install as a persistent skill (Business, Enterprise, Edu, Teachers, Healthcare plans)** - - Fetch this Base MCP skill and follow it to onboard me — including any reference or plugin files it tells you to load: `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/SKILL.md` - + 1. In ChatGPT, open [**Settings → Skills**](https://chatgpt.com/skills) + 2. Click **Add skill** and upload the downloaded `base-mcp.zip` + 3. Enable the skill for the conversations where you want it active - ChatGPT will fetch the skill via web_request, verify the Base MCP connection from the previous step, and run the short onboarding flow defined in the skill. Works on any ChatGPT plan. + See [Skills in ChatGPT](https://help.openai.com/en/articles/20001066-skills-in-chatgpt) for details. ```bash Terminal diff --git a/docs/ai-agents/skills/SKILL.md b/docs/ai-agents/skills/SKILL.md index f0794e318..acdfaae8f 100644 --- a/docs/ai-agents/skills/SKILL.md +++ b/docs/ai-agents/skills/SKILL.md @@ -2,7 +2,7 @@ title: "Base MCP Skill" description: "Base MCP — gives your AI assistant access to a Base account via the Base MCP server (mcp.base.org). Wallet, portfolio, sending, swapping, signing, batched contract calls, and transaction history on Base." name: base-mcp -version: 0.2.0 +version: 0.1.0 --- # Base MCP @@ -12,17 +12,11 @@ version: 0.2.0 > > Including conversations that jump straight to a plugin topic. Onboarding is short — see below. -## How this skill loads references and plugins - -This skill is intentionally lightweight. The detailed reference and plugin files are **not bundled** — fetch them on demand from the Base docs site using `web_request` (or the harness's HTTP tool, if available). Always fetch the URLs exactly as written below — they end in `.md` so you get clean markdown instead of rendered HTML. - -Only fetch a reference or plugin file the first time you need it in a session; once loaded, its contents are in your context. - ## Detection -The Base MCP exposes its tools to the harness when connected. If no Base MCP tool is callable, the MCP server is not installed: direct the user to `https://docs.base.org/ai-agents/quickstart` (or fetch `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/install.md` for app-specific steps) and stop. +The Base MCP exposes its tools to the harness when connected. If no Base MCP tool is callable, the MCP server is not installed: direct the user to https://docs.base.org/ai-agents/quickstart (or load [references/install.md](references/install.md) for app-specific steps) and stop. -If Base MCP tools are available, fetch `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/tone.md` — its rules apply for the entire conversation — then continue to Onboarding. +If Base MCP tools are available, load [references/tone.md](references/tone.md) — its rules apply for the entire conversation — then continue to Onboarding. ## Onboarding @@ -40,15 +34,15 @@ Keep it short. Do this once per session, before doing real work: The Base MCP advertises its own tool catalog to the harness. Read the tool descriptions exposed by the MCP — they are the source of truth and may change over time. Do not assume a fixed list; do not preload a tool catalog from this skill. -Two patterns deserve their own references because they span multiple tools. Fetch each one only when you need it: +Two patterns deserve their own references because they span multiple tools: -| Topic | Fetch from | +| Topic | Reference | |-------|-----------| -| Approval flow (for any write tool that returns an approval URL) | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/approval-mode.md` | -| Batched contract calls (EIP-5792) | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/batch-calls.md` | -| Custom / non-native plugins and the `web_request` allowlist | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/custom-plugins.md` | -| Platform install steps | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/install.md` | -| Tone and language rules | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/tone.md` | +| Approval flow (for any write tool that returns an approval URL) | [references/approval-mode.md](references/approval-mode.md) | +| Batched contract calls (EIP-5792) | [references/batch-calls.md](references/batch-calls.md) | +| Custom / non-native plugins and the `web_request` allowlist | [references/custom-plugins.md](references/custom-plugins.md) | +| Platform install steps | [references/install.md](references/install.md) | +| Tone and language rules | [references/tone.md](references/tone.md) | ## Plugins @@ -56,15 +50,21 @@ Plugins extend Base MCP with partner-specific functionality (lending, swaps, per Plugins currently maintained alongside this skill (the **native plugins**): -| Plugin | Fetch from | +| Plugin | Reference | |--------|-----------| -| Morpho | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/plugins/morpho.md` | -| Moonwell | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/plugins/moonwell.md` | -| Uniswap | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/plugins/uniswap.md` | -| Avantis | `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/plugins/avantis.md` | +| Morpho | [plugins/morpho.md](plugins/morpho.md) | +| Moonwell | [plugins/moonwell.md](plugins/moonwell.md) | +| Uniswap | [plugins/uniswap.md](plugins/uniswap.md) | +| Avantis | [plugins/avantis.md](plugins/avantis.md) | -Fetch a plugin reference only when the user's request matches it. For a plugin's own tools, defer to the descriptions the plugin's MCP exposes — this skill does not duplicate them. +Load a plugin reference only when the user's request matches it. For a plugin's own tools, defer to the descriptions the plugin's MCP exposes — this skill does not duplicate them. ### Native plugins vs. custom / user-supplied plugins -Native plugins are allowlisted in the Base MCP `web_request` tool and work everywhere. Custom or user-supplied plugins usually aren't allowlisted — fetch `https://base-a060aa97-youssef-update-agents.mintlify.app/ai-agents/skills/references/custom-plugins.md` for the decision tree on which HTTP path to use (harness HTTP tool vs. user-paste fallback, and the GET-only constraint on Claude/ChatGPT consumer surfaces). +Native plugins are allowlisted in the Base MCP `web_request` tool and work everywhere. Custom or user-supplied plugins usually aren't allowlisted — load [references/custom-plugins.md](references/custom-plugins.md) for the decision tree on which HTTP path to use (harness HTTP tool vs. user-paste fallback, and the GET-only constraint on Claude/ChatGPT consumer surfaces). + +## Installation + +```bash +npx skills add base/skills --skill base-mcp +```