import { useCallback, useState } from "react"; import { createRoot } from "react-dom/client"; import { ThemeProvider } from "@cloudflare/agents-ui/hooks"; import { ConnectionIndicator, ModeToggle, PoweredByAgents, type ConnectionStatus } from "@cloudflare/agents-ui"; import { Button, Badge, Surface, Text, Empty } from "@cloudflare/kumo"; import { CurrencyDollarIcon, MegaphoneIcon, HashIcon, PaperPlaneRightIcon, TrashIcon, XIcon, CheckIcon, InfoIcon, WarningCircleIcon, CheckCircleIcon } from "@phosphor-icons/react"; import { useAgent } from "agents/react"; import { nanoid } from "nanoid"; import "./styles.css"; let sessionId = localStorage.getItem("x402-session"); if (!sessionId) { sessionId = nanoid(8); localStorage.setItem("x402-session", sessionId); } interface ToolResult { label: string; text: string; isError: boolean; timestamp: number; } interface PaymentInfo { resource: string; address: string; network: string; amount: string; id: string; } function App() { const [status, setStatus] = useState("connecting"); const [results, setResults] = useState([]); const [payment, setPayment] = useState(null); const agent = useAgent({ agent: "pay-agent", name: sessionId!, onOpen: useCallback(() => setStatus("connected"), []), onClose: useCallback(() => setStatus("disconnected"), []), onMessage: useCallback((message: MessageEvent) => { try { const parsed = JSON.parse(message.data); if ( parsed.type === "payment_required" && Array.isArray(parsed.requirements) ) { const p = parsed.requirements[0] || {}; const amt = (Number(p.maxAmountRequired) / 1e6).toString(); setPayment({ resource: p.resource || "—", address: p.payTo || "—", network: p.network || "—", amount: amt, id: parsed.confirmationId || "—" }); } } catch { // ignore non-JSON messages } }, []) }); const handleCallTool = async ( toolName: string, args: Record ) => { try { const res = (await agent.call("callTool", [toolName, args])) as { text: string; isError: boolean; }; setResults((prev) => [ { label: toolName, text: res.text, isError: res.isError, timestamp: Date.now() }, ...prev ]); } catch (err) { setResults((prev) => [ { label: toolName, text: err instanceof Error ? err.message : String(err), isError: true, timestamp: Date.now() }, ...prev ]); } }; const handlePayment = (confirmed: boolean) => { if (!payment) return; agent.call("resolvePayment", [payment.id, confirmed]); setPayment(null); }; return (

x402 MCP

Paid MCP Tools (x402) The echo tool is free. The{" "} square tool costs $0.01 — calling it triggers a payment confirmation between the client agent and the MCP server using the x402 protocol.
{status === "disconnected" && ( } title="Disconnected" description="Could not connect to the agent. Make sure the server is running." /> )} {status === "connected" && ( <>
{payment && ( handlePayment(true)} onCancel={() => handlePayment(false)} /> )} {results.length > 0 && (
Results
{results.map((r) => (
{r.isError ? ( ) : ( )}
{r.label}

{r.text}

{new Date(r.timestamp).toLocaleTimeString()}
))}
)} )}
); } function EchoForm({ onCall }: { onCall: (tool: string, args: Record) => Promise; }) { const [message, setMessage] = useState(""); const [loading, setLoading] = useState(false); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!message.trim()) return; setLoading(true); await onCall("echo", { message }); setLoading(false); setMessage(""); }; return (
Echo free
); } function SquareForm({ onCall }: { onCall: (tool: string, args: Record) => Promise; }) { const [number, setNumber] = useState(""); const [loading, setLoading] = useState(false); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (number === "") return; setLoading(true); await onCall("square", { number: Number(number) }); setLoading(false); setNumber(""); }; return (
Square $0.01
Triggers the x402 payment flow.
); } function PaymentModal({ payment, onConfirm, onCancel }: { payment: PaymentInfo; onConfirm: () => void; onCancel: () => void; }) { return (
Payment Required A paid tool has been requested. Confirm to continue.
Resource {payment.resource} Pay to {payment.address} Network {payment.network} Amount ${payment.amount} USD
); } createRoot(document.getElementById("root")!).render( );