Skip to main content
Glama
Bichev
by Bichev
ARCHITECTURE.mdโ€ข48 kB
# ๐Ÿ—๏ธ Coinbase MCP - Technical Architecture ## ๐Ÿ“‹ Table of Contents 1. [Overview](#overview) 2. [System Architecture](#system-architecture) 3. [Component Breakdown](#component-breakdown) 4. [Real vs. Simulated Components](#real-vs-simulated-components) 5. [Data Flow](#data-flow) 6. [Technology Stack](#technology-stack) 7. [Comparison with Alternatives](#comparison-with-alternatives) 8. [Code Examples](#code-examples) 9. [Deployment Architecture](#deployment-architecture) 10. [Security & Best Practices](#security--best-practices) --- ## Overview This project implements a **hybrid architecture** combining: - **Real market data** from Coinbase Public API - **Simulated wallet** for educational crypto transactions - **Official MCP protocol** for AI agent integration - **Modern web stack** for beautiful UX **Philosophy**: Real education without real risk! ๐ŸŽ“ --- ## System Architecture ### High-Level Architecture Diagram ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ CLIENT LAYER โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Cursor IDE โ”‚ โ”‚ Claude โ”‚ โ”‚ Web Browser โ”‚ โ”‚ โ”‚ โ”‚ (MCP Client)โ”‚ โ”‚ Desktop โ”‚ โ”‚ (React App) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ MCP SERVER โ”‚ โ”‚ API SERVER โ”‚ โ”‚ (stdio transport) โ”‚ โ”‚ (HTTP REST) โ”‚ โ”‚ Port: stdio โ”‚ โ”‚ Port: 3002 โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ 13 MCP Tools: โ”‚ โ”‚ REST Endpoints: โ”‚ โ”‚ โ€ข get_spot_price โ”‚ โ”‚ โ€ข GET /api/v1/* โ”‚ โ”‚ โ€ข analyze_price โ”‚ โ”‚ โ€ข POST /api/v1/* โ”‚ โ”‚ โ€ข buy_virtual_beer โ”‚ โ”‚ โ€ข Swagger UI โ”‚ โ”‚ โ€ข get_wallet โ”‚ โ”‚ โ€ข Static files โ”‚ โ”‚ โ€ข ... โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ SHARED BUSINESS LOGIC โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ CoinbaseClient โ”‚ โ”‚ โ”‚ โ”‚ (Wrapper for Coinbase API) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ DemoWalletClient โ”‚ โ”‚ โ”‚ โ”‚ (Transaction Simulator) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Coinbase API โ”‚ โ”‚ In-Memory Store โ”‚ โ”‚ (Public v2) โ”‚ โ”‚ (Demo Wallet) โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ Real Data: โ”‚ โ”‚ Simulated: โ”‚ โ”‚ โ€ข Prices โ”‚ โ”‚ โ€ข Balances โ”‚ โ”‚ โ€ข Market Stats โ”‚ โ”‚ โ€ข Transactions โ”‚ โ”‚ โ€ข Assets โ”‚ โ”‚ โ€ข Inventory โ”‚ โ”‚ โ€ข History โ”‚ โ”‚ โ€ข Beer Count ๐Ÿบ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ EXTERNAL SERVICES โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ OpenAI Services (Optional) โ”‚ โ”‚ โ”‚ โ”‚ โ€ข GPT-4 Turbo (Chat intelligence) โ”‚ โ”‚ โ”‚ โ”‚ โ€ข Whisper (Multi-language voice input) โ”‚ โ”‚ โ”‚ โ”‚ โ€ข TTS (Text-to-speech responses) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` --- ## Component Breakdown ### 1. MCP Server (`/mcp-server`) **Purpose**: Expose crypto tools to AI agents (Cursor, Claude Desktop) **Technology**: ```typescript import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; ``` **Communication**: stdio (standard input/output) **Tools Registered**: 13 total - 8 Market data tools - 5 Transaction/wallet tools **Example Tool Registration**: ```typescript this.server.registerTool( 'buy_virtual_beer', { title: 'Buy Virtual Beer with Crypto', description: 'Purchase virtual beer using cryptocurrency', inputSchema: BuyVirtualBeerInputSchema.shape }, async ({ quantity, currency, pricePerBeer }) => { const result = await this.demoWalletClient.buyVirtualBeer( quantity, currency, pricePerBeer ); return { content: [{ type: 'text', text: result.message }] }; } ); ``` ### 2. API Server (`/api-server`) **Purpose**: REST API for web frontend **Technology**: ```typescript import express from 'express'; import cors from 'cors'; import helmet from 'helmet'; ``` **Communication**: HTTP REST (port 3002) **Endpoints**: 20+ REST endpoints **Key Features**: - Rate limiting (100 req/15min) - Swagger documentation (`/api-docs`) - CORS enabled - Static file serving - Compression **Example Endpoint**: ```typescript app.post('/api/v1/wallet/buy-beer', async (req, res) => { const { quantity, currency, pricePerBeer } = req.body; const result = await demoWalletClient.buyVirtualBeer( quantity, currency, pricePerBeer ); res.json({ success: result.success, data: result.transaction, message: result.message }); }); ``` ### 3. Frontend Application (`/frontend`) **Purpose**: Beautiful web UI for users **Technology**: ```typescript // React + TypeScript + Vite import React from 'react'; import { QueryClient } from '@tanstack/react-query'; import { BrowserRouter } from 'react-router-dom'; ``` **Pages**: - `/` - Chat Interface (with voice!) - `/wallet` - Virtual Wallet & Beer purchases - `/mcp-tester` - MCP tool testing - `/api-explorer` - Interactive API docs - `/tutorial` - Comprehensive guide - `/presentations` - Business slides - `/architecture` - Architecture diagrams **Key Services**: ```typescript // AI Service - Orchestrates GPT-4 + MCP tools aiService.processMessage("Buy me a beer") โ†’ Calls GPT-4 for intent understanding โ†’ Executes MCP tools via API โ†’ Returns formatted response // Voice Service - Whisper + TTS voiceService.transcribeAudio(blob) // โ†’ Multi-language voiceService.textToSpeech(text) // โ†’ Natural voice ``` ### 4. Shared Business Logic #### CoinbaseClient (Real Data Layer) ```typescript export class CoinbaseClient { private client: AxiosInstance; private baseUrl = 'https://api.coinbase.com/v2'; async getSpotPrice(currencyPair: string) { // Makes REAL API call to Coinbase const response = await this.client.get(`/prices/${currencyPair}/spot`); return response.data; // Real current price! } async getStats(currencyPair: string) { // Gets REAL 24-hour market statistics const response = await this.client.get(`/prices/${currencyPair}/stats`); return response.data; } } ``` **What it does**: - โœ… Fetches real-time cryptocurrency prices - โœ… Gets actual market statistics - โœ… Retrieves genuine historical data - โœ… Provides real asset information - โŒ Does NOT execute real trades - โŒ Does NOT access wallets #### DemoWalletClient (Simulation Layer) ```typescript export class DemoWalletClient { private wallet: DemoWallet = { balances: { USD: 1000, BTC: 0, ETH: 0 }, transactions: [], inventory: { beers: 0, items: [] }, createdAt: new Date(), lastUpdated: new Date() }; async simulatePurchase(from: string, to: string, amount: number) { // 1. Get REAL price const priceData = await this.coinbaseClient.getSpotPrice(`${to}-USD`); const price = parseFloat(priceData.data.amount); // โ† REAL // 2. Calculate conversion const cryptoAmount = amount / price; // 3. Check SIMULATED balance if (this.wallet.balances[from] < amount) { throw new Error('Insufficient balance'); } // 4. Update SIMULATED balances this.wallet.balances[from] -= amount; this.wallet.balances[to] += cryptoAmount; // 5. Record SIMULATED transaction this.wallet.transactions.push({ /* ... */ }); return transaction; } async buyVirtualBeer(quantity: number, currency: string) { // Check crypto balance (simulated) const balance = this.wallet.balances[currency]; // Get real price for calculation const price = await this.coinbaseClient.getSpotPrice(`${currency}-USD`); const cryptoNeeded = (quantity * 5) / parseFloat(price.data.amount); if (balance < cryptoNeeded) { // Smart suggestion with real prices! return { success: false, needsMoreCrypto: true, message: `You need ${cryptoNeeded} ${currency} but only have ${balance}` }; } // Execute purchase (simulated) this.wallet.balances[currency] -= cryptoNeeded; this.wallet.inventory.beers += quantity; return { success: true }; } } ``` **What it does**: - โœ… Manages virtual balances (in-memory) - โœ… Simulates transactions - โœ… Tracks inventory (beers!) - โœ… Uses REAL prices for calculations - โŒ No blockchain involved - โŒ No real money moved --- ## Real vs. Simulated Components ### โœ… What's REAL #### 1. **Coinbase Market Data** ```typescript // REAL API Call const response = await axios.get( 'https://api.coinbase.com/v2/prices/BTC-USD/spot' ); // REAL Response { "data": { "amount": "110464.17", // โ† Live BTC price "base": "BTC", "currency": "USD" } } ``` **No authentication needed** - Public API! #### 2. **MCP Protocol** ```typescript // Official MCP SDK from Anthropic import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; // Standard MCP tool registration server.registerTool('get_spot_price', schema, handler); // Works with any MCP client! ``` #### 3. **OpenAI Services** (Optional) ```typescript // REAL GPT-4 API calls const completion = await openai.chat.completions.create({ model: 'gpt-4-turbo-preview', messages: conversation, tools: availableTools // Our 13 MCP tools }); // REAL Whisper transcription const transcription = await openai.audio.transcriptions.create({ file: audioFile, model: 'whisper-1' }); // REAL TTS audio generation const speech = await openai.audio.speech.create({ model: 'tts-1', voice: 'alloy', input: text }); ``` ### ๐ŸŽฎ What's SIMULATED #### 1. **Wallet Balances** ```typescript // Stored in-memory (not on blockchain) private wallet: DemoWallet = { balances: { USD: 1000.00, // Virtual USD BTC: 0.00004531, // Virtual BTC ETH: 0.0131 // Virtual ETH } }; ``` **Reset on server restart!** #### 2. **Transactions** ```typescript // Stored in array (not on blockchain) transactions: [ { id: "tx_1735234567_abc123", type: "buy", fromCurrency: "USD", toCurrency: "BTC", fromAmount: 5.00, toAmount: 0.00004531, price: 110464.17, // โ† Price was REAL at time of transaction timestamp: new Date() } ] ``` **No permanent database!** #### 3. **Virtual Inventory** ```typescript // Our custom inventory system inventory: { beers: 3, // Virtual beers owned items: [ { id: "tx_...", name: "Beer", emoji: "๐Ÿบ", quantity: 1, purchasePrice: 0.00004531, purchaseCurrency: "BTC", purchaseDate: new Date() } ] } ``` **Educational only!** --- ## Data Flow ### Flow 1: Simple Price Query ``` User: "What's the Bitcoin price?" โ†“ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ 1. CHAT UI (ChatInterface.tsx) โ”‚ โ”‚ โ†’ User types message โ”‚ โ”‚ โ†’ Sends to aiService โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ†“ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ 2. AI SERVICE (aiService.ts) โ”‚ โ”‚ โ†’ Sends to GPT-4 (OpenAI) โ† REAL AI โ”‚ โ”‚ โ†’ GPT-4 selects tool: get_spot_price โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ†“ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ 3. TOOL EXECUTOR (executeTool) โ”‚ โ”‚ โ†’ HTTP GET /api/v1/prices/BTC-USD โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ†“ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ 4. API SERVER (index.ts) โ”‚ โ”‚ โ†’ Receives request โ”‚ โ”‚ โ†’ Calls coinbaseClient.getSpotPrice()โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ†“ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ 5. COINBASE CLIENT (coinbase-client.ts) โ”‚ โ”‚ โ†’ axios.get('https://api.coinbase... โ”‚ โ”‚ โ†’ Gets REAL data from Coinbase โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ†“ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ 6. COINBASE API (External) โ”‚ โ”‚ โ†’ Returns real BTC price: $110,464 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ†“ [Returns back through stack] โ†“ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ 7. CHAT UI โ”‚ โ”‚ โ†’ Displays: "BTC-USD: $110,464" โ”‚ โ”‚ โ†’ Shows tool call details โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ### Flow 2: Circular Economy (USD โ†’ BTC โ†’ Beer) ``` User: "Buy me a beer" โ†“ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ STEP 1: Check Wallet โ”‚ โ”‚ AI: Let me check your BTC balance... โ”‚ โ”‚ Tool: get_virtual_wallet โ”‚ โ”‚ Result: BTC: 0.00000000 โ† SIMULATED โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ†“ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ STEP 2: Try to Buy Beer โ”‚ โ”‚ Tool: buy_virtual_beer โ”‚ โ”‚ Check: balance (0) < needed (0.00004531) โ† SIMULATED โ”‚ โ”‚ Result: โŒ Insufficient BTC! โ”‚ โ”‚ Suggestion: "Buy $5 worth of BTC first" โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ†“ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ User: "OK, buy $5 of Bitcoin" โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ†“ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ STEP 3: Buy BTC with USD โ”‚ โ”‚ Tool: simulate_btc_purchase โ”‚ โ”‚ โ”œโ”€ Get price from Coinbase โ† REAL ($110,464) โ”‚ โ”‚ โ”œโ”€ Calculate: $5 / $110,464 = 0.00004531 BTC โ”‚ โ”‚ โ”œโ”€ Check USD balance: $1000 โ† SIMULATED โ”‚ โ”‚ โ”œโ”€ Deduct: USD -= $5 โ† SIMULATED โ”‚ โ”‚ โ””โ”€ Add: BTC += 0.00004531 โ† SIMULATED โ”‚ โ”‚ Result: โœ… You now have 0.00004531 BTC โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ†“ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ User: "Now buy the beer!" โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ†“ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ STEP 4: Buy Beer with BTC โ”‚ โ”‚ Tool: buy_virtual_beer โ”‚ โ”‚ โ”œโ”€ Get price from Coinbase โ† REAL ($110,464) โ”‚ โ”‚ โ”œโ”€ Calculate needed: 0.00004531 BTC โ”‚ โ”‚ โ”œโ”€ Check BTC balance: 0.00004531 โ† SIMULATED โ”‚ โ”‚ โ”œโ”€ Deduct: BTC -= 0.00004531 โ† SIMULATED โ”‚ โ”‚ โ””โ”€ Add: beers += 1 โ† SIMULATED โ”‚ โ”‚ Result: ๐Ÿบ You have 1 beer! โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ FINAL STATE: โ”œโ”€ USD: $995.00 (was $1000) โ”œโ”€ BTC: 0.00000000 (was 0.00004531) โ””โ”€ ๐Ÿบ Beers: 1 (was 0) All balance changes: SIMULATED All prices used: REAL from Coinbase! ``` --- ## Technology Stack ### Backend Technologies ```yaml MCP Server: - Runtime: Node.js 18+ - Language: TypeScript 5.3+ - MCP SDK: @modelcontextprotocol/sdk ^1.0.0 - HTTP Client: axios ^1.6.2 - Validation: zod ^3.22.4 - Transport: stdio (standard input/output) API Server: - Framework: Express.js - Language: TypeScript - Security: helmet, cors - Docs: Swagger (swagger-jsdoc, swagger-ui-express) - Logging: winston - Rate Limiting: express-rate-limit - Compression: compression middleware Shared: - coinbase-client.ts (Wrapper for Coinbase API) - demo-wallet-client.ts (Transaction simulator) - types.ts (TypeScript interfaces) ``` ### Frontend Technologies ```yaml Framework: - React 18 - TypeScript - Vite (Build tool) Routing: - react-router-dom ^6 State Management: - @tanstack/react-query (Server state) - React hooks (Local state) UI/Styling: - TailwindCSS 3 - Heroicons (Icons) - lucide-react (Additional icons) - clsx (Conditional classes) Services: - OpenAI SDK (GPT-4, Whisper, TTS) - axios (HTTP client) - Custom aiService - Custom voiceService - Custom chatSessionService ``` ### External APIs ```yaml Coinbase Public API v2: - Base URL: https://api.coinbase.com/v2 - Authentication: None (public endpoints) - Rate Limits: ~10,000 req/hour - Endpoints Used: โ€ข /prices/{pair}/spot โ€ข /prices/{pair}/stats โ€ข /prices/{pair}/historic โ€ข /currencies โ€ข /exchange-rates โ€ข /time OpenAI API (Optional): - GPT-4 Turbo (gpt-4-turbo-preview) - Whisper (whisper-1) - TTS (tts-1) - Authentication: API key required - Used for: Chat AI, voice features ``` --- ## Comparison with Alternatives ### Our Implementation vs. Base MCP | Feature | Our Demo System | Base MCP | |---------|-----------------|----------| | **Purpose** | Education & Demo | Real Production | | **Money** | Virtual (safe) | Real crypto | | **Setup** | Zero config | API keys + wallet | | **Blockchain** | No blockchain | Base network | | **Transactions** | Instant | 2-5 sec confirmation | | **Cost** | Free | Gas fees | | **Risk** | Zero | Real financial risk | | **Learning** | Perfect โœ… | Too risky for beginners | | **Features** | Full control | Limited to API | **Base MCP Example** (What we didn't use): ```typescript // Requires real setup import { WalletClient } from '@coinbase/coinbase-sdk'; const client = WalletClient.configureFromJson({ apiKeyName: process.env.CDP_API_KEY_NAME, privateKey: process.env.CDP_PRIVATE_KEY }); // Real transaction (costs real money!) const transfer = await wallet.createTransfer({ amount: 0.00001, assetId: 'btc', destination: recipientAddress, network: 'base-sepolia' }); await transfer.wait(); // Wait for blockchain confirmation ``` ### Our Implementation vs. x402 Protocol | Feature | Our Demo System | x402 Protocol | |---------|-----------------|---------------| | **Use Case** | Crypto transactions | API micropayments | | **Payment For** | Virtual goods | Data/services | | **Flow** | USDโ†’Cryptoโ†’Beer | HTTP 402โ†’Payโ†’Data | | **Technology** | Custom logic | HTTP 402 standard | | **Setup** | None | Wallet with USDC | | **Education** | Perfect โœ… | Advanced topic | **x402 Example** (What we didn't use): ```typescript // Requires wallet and USDC import { withPaymentInterceptor } from 'x402-axios'; import { privateKeyToAccount } from 'viem/accounts'; const account = privateKeyToAccount(privateKey); const client = withPaymentInterceptor(axios.create(), account); // Automatically pays if server responds with 402 const response = await client.get('/paid-endpoint'); // If HTTP 402, pays with USDC, then retries ``` ### Why We Built Custom **Advantages of Our Approach**: โœ… **Zero Dependencies on Real Money** - No wallet setup - No blockchain - No gas fees โœ… **Perfect for Education** - Safe experimentation - Unlimited "resets" - Clear learning path โœ… **Full Feature Control** - Add any feature we want - Custom UI/UX - Beer inventory! โœ… **Fast Development** - No blockchain wait times - Instant transactions - Quick iterations โœ… **Wide Compatibility** - Works in any browser - No MetaMask needed - No wallet extensions **When to Use Alternatives**: Use **Base MCP** if: - Building real crypto app - Need actual blockchain transactions - Have Coinbase developer account - Production use case Use **x402** if: - Building paid API service - Micropayments for data - Want HTTP 402 standard - API monetization Use **Our System** if: - Learning crypto concepts โœ… - Demo/presentation - Educational platform - Safe experimentation - Quick prototyping --- ## Code Examples ### Example 1: Fetching Real Price ```typescript // coinbase-client.ts export class CoinbaseClient { async getSpotPrice(currencyPair: string): Promise<CoinbaseSpotPrice> { try { // REAL API call to Coinbase const response = await this.client.get(`/prices/${currencyPair}/spot`); // Example response: // { // "data": { // "amount": "110464.17", // "base": "BTC", // "currency": "USD" // } // } return response.data; } catch (error) { throw this.handleError(error, 'Failed to fetch spot price'); } } } ``` ### Example 2: Simulating Purchase ```typescript // demo-wallet-client.ts export class DemoWalletClient { async simulatePurchase( fromCurrency: string, toCurrency: string, amount: number, description?: string ): Promise<DemoTransaction> { const from = fromCurrency.toUpperCase(); const to = toCurrency.toUpperCase(); // STEP 1: Check SIMULATED balance const currentBalance = this.getBalance(from); if (currentBalance < amount) { throw new Error(`Insufficient ${from} balance`); } // STEP 2: Get REAL price from Coinbase const priceData = await this.coinbaseClient.getSpotPrice(`${to}-USD`); const currentPrice = parseFloat(priceData.data.amount); // โ† REAL const cryptoAmount = amount / currentPrice; // STEP 3: Create transaction object const transaction: DemoTransaction = { id: `tx_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, type: 'buy', fromCurrency: from, toCurrency: to, fromAmount: amount, toAmount: cryptoAmount, price: currentPrice, // โ† REAL price at time of transaction description: description || `Bought ${to} with ${from}`, timestamp: new Date(), status: 'completed' }; // STEP 4: Update SIMULATED balances (in-memory) this.wallet.balances[from] -= transaction.fromAmount; this.wallet.balances[to] = (this.wallet.balances[to] || 0) + transaction.toAmount; // STEP 5: Store SIMULATED transaction (in-memory array) this.wallet.transactions.unshift(transaction); this.wallet.lastUpdated = new Date(); return transaction; } } ``` ### Example 3: Buying Beer with Crypto ```typescript // demo-wallet-client.ts async buyVirtualBeer( quantity: number = 1, currency: string = 'BTC', pricePerBeer: number = 5 ): Promise<BeerPurchaseResult> { const crypto = currency.toUpperCase(); const totalUsdCost = quantity * pricePerBeer; // STEP 1: Get REAL crypto price const priceData = await this.coinbaseClient.getSpotPrice(`${crypto}-USD`); const cryptoPrice = parseFloat(priceData.data.amount); // โ† REAL const cryptoNeeded = totalUsdCost / cryptoPrice; // STEP 2: Check SIMULATED balance const currentBalance = this.getBalance(crypto); if (currentBalance < cryptoNeeded) { // Not enough - return helpful error return { success: false, needsMoreCrypto: true, suggestedAmount: totalUsdCost, message: `โŒ Insufficient ${crypto}!\n` + `Need: ${cryptoNeeded.toFixed(8)} ${crypto}\n` + `Have: ${currentBalance.toFixed(8)} ${crypto}\n\n` + `๐Ÿ’ก Buy $${totalUsdCost} worth of ${crypto} first!` }; } // STEP 3: Execute SIMULATED beer purchase const transaction = { id: `tx_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, type: 'buy' as const, fromCurrency: crypto, toCurrency: 'BEER', fromAmount: cryptoNeeded, toAmount: quantity, price: cryptoPrice, // โ† REAL price description: `๐Ÿบ Bought ${quantity} beer(s) with ${crypto}`, timestamp: new Date(), status: 'completed' as const }; // STEP 4: Update SIMULATED state this.wallet.balances[crypto] -= cryptoNeeded; this.wallet.inventory.beers += quantity; this.wallet.inventory.items.push({ id: transaction.id, name: 'Beer', emoji: '๐Ÿบ', quantity, purchasePrice: cryptoNeeded, purchaseCurrency: crypto, purchaseDate: new Date() }); this.wallet.transactions.unshift(transaction); return { success: true, transaction, message: `๐Ÿบ Beer Purchase Successful!\n` + `Bought ${quantity} beer(s) for ${cryptoNeeded.toFixed(8)} ${crypto}\n` + `Total beers: ${this.wallet.inventory.beers}` }; } ``` ### Example 4: MCP Tool Registration ```typescript // index.ts (MCP Server) private setupTools(): void { // Register tool with MCP protocol this.server.registerTool( 'buy_virtual_beer', // Tool name { title: 'Buy Virtual Beer with Crypto', description: 'Purchase virtual beer using cryptocurrency', inputSchema: BuyVirtualBeerInputSchema.shape // Zod schema }, async ({ quantity, currency, pricePerBeer }) => { // Execute business logic const result = await this.demoWalletClient.buyVirtualBeer( quantity, currency, pricePerBeer ); // Return MCP-formatted response return { content: [{ type: 'text', text: result.message }] }; } ); } ``` ### Example 5: AI Tool Orchestration ```typescript // aiService.ts (Frontend) async processMessage(userMessage: string): Promise<AIResponse> { // Send to GPT-4 with available tools const response = await openai.chat.completions.create({ model: 'gpt-4-turbo-preview', messages: this.conversation, tools: availableTools.map(tool => ({ type: 'function', function: { name: tool.name, description: tool.description, parameters: tool.parameters } })), tool_choice: 'auto' // Let GPT-4 decide which tools to use }); // Execute any tool calls GPT-4 requested if (response.choices[0].message.tool_calls) { for (const toolCall of response.choices[0].message.tool_calls) { const result = await this.executeTool({ tool: toolCall.function.name, parameters: JSON.parse(toolCall.function.arguments) }); // Add result back to conversation this.conversation.push({ role: 'tool', tool_call_id: toolCall.id, content: JSON.stringify(result.result) }); } // Get final response from GPT-4 incorporating tool results const finalResponse = await openai.chat.completions.create({ model: 'gpt-4-turbo-preview', messages: this.conversation }); return { message: finalResponse.choices[0].message.content, toolCalls: executedTools }; } } ``` --- ## Deployment Architecture ### Development (Current) ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ localhost:5173 (Frontend - Vite dev) โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ€ข Hot reload โ”‚ โ”‚ โ€ข Source maps โ”‚ โ”‚ โ€ข Dev tools โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ localhost:3002 (API Server - Node) โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ€ข Express dev mode โ”‚ โ”‚ โ€ข Winston logging โ”‚ โ”‚ โ€ข Auto-restart (nodemon) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ stdio (MCP Server for Cursor) โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ€ข Runs when Cursor starts โ”‚ โ”‚ โ€ข stdio communication โ”‚ โ”‚ โ€ข Shared with API server code โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ### Production (Possible) ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Vercel / Netlify (Frontend) โ”‚ โ”‚ โ€ข Static build (npm run build) โ”‚ โ”‚ โ€ข Global CDN โ”‚ โ”‚ โ€ข Auto SSL โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Vercel Serverless (API) โ”‚ โ”‚ โ€ข Express app as serverless fn โ”‚ โ”‚ โ€ข Auto-scaling โ”‚ โ”‚ โ€ข Environment variables โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ External APIs โ”‚ โ”‚ โ€ข Coinbase (always available) โ”‚ โ”‚ โ€ข OpenAI (if configured) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` --- ## Security & Best Practices ### What We Do Right โœ… ```typescript // 1. Rate Limiting const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100 // 100 requests per window }); // 2. Input Validation (Zod schemas) const SimulatePurchaseInputSchema = z.object({ fromCurrency: z.string(), toCurrency: z.string(), amount: z.number().positive() }); // 3. Error Handling try { const result = await coinbaseClient.getSpotPrice(pair); return result; } catch (error) { logger.error('API error:', error); throw new CoinbaseAPIError(error.message); } // 4. CORS Configuration app.use(cors({ origin: process.env.ALLOWED_ORIGINS || '*', credentials: true })); // 5. Security Headers (Helmet) app.use(helmet()); // 6. Request Logging (Winston) logger.info('Request received', { method: req.method, path: req.path, ip: req.ip }); ``` ### Security Notes **Safe for Demo**: - โœ… No real money at risk - โœ… In-memory storage only - โœ… No sensitive data stored - โœ… Public API only (no auth needed) **Production Considerations** (if upgrading): - ๐Ÿ” Use environment variables for API keys - ๐Ÿ” Implement user authentication - ๐Ÿ” Use database for persistence - ๐Ÿ” Add request signing - ๐Ÿ” Implement withdrawal limits - ๐Ÿ” Add 2FA for transactions - ๐Ÿ” Server-side API key management (not browser) --- ## File Structure ``` coinbase-chat-mcp/ โ”‚ โ”œโ”€โ”€ mcp-server/ # MCP Protocol Server โ”‚ โ”œโ”€โ”€ src/ โ”‚ โ”‚ โ”œโ”€โ”€ index.ts # MCP tool registration โ”‚ โ”‚ โ”œโ”€โ”€ coinbase-client.ts # Coinbase API wrapper (REAL) โ”‚ โ”‚ โ”œโ”€โ”€ demo-wallet-client.ts # Transaction simulator (SIMULATED) โ”‚ โ”‚ โ””โ”€โ”€ types.ts # TypeScript interfaces โ”‚ โ”œโ”€โ”€ dist/ # Compiled JavaScript โ”‚ โ””โ”€โ”€ package.json # Dependencies โ”‚ โ”œโ”€โ”€ api-server/ # REST API Server โ”‚ โ”œโ”€โ”€ src/ โ”‚ โ”‚ โ”œโ”€โ”€ index.ts # Express routes โ”‚ โ”‚ โ”œโ”€โ”€ coinbase-client.ts # Same as MCP server โ”‚ โ”‚ โ”œโ”€โ”€ demo-wallet-client.ts # Same as MCP server โ”‚ โ”‚ โ””โ”€โ”€ types.ts # Same types โ”‚ โ”œโ”€โ”€ dist/ # Compiled JavaScript โ”‚ โ””โ”€โ”€ package.json โ”‚ โ”œโ”€โ”€ frontend/ # React Web Application โ”‚ โ”œโ”€โ”€ src/ โ”‚ โ”‚ โ”œโ”€โ”€ App.tsx # Main app & routing โ”‚ โ”‚ โ”œโ”€โ”€ components/ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ Layout.tsx # Sidebar navigation โ”‚ โ”‚ โ”œโ”€โ”€ pages/ โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ ChatInterface.tsx # AI chat with voice ๐ŸŽค โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ Wallet.tsx # Virtual wallet UI ๐Ÿบโ‚ฟ โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ APIExplorer.tsx # Interactive API docs โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ ... โ”‚ โ”‚ โ”œโ”€โ”€ services/ โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ aiService.ts # GPT-4 + tool orchestration โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ voiceService.ts # Whisper + TTS โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ chatSessionService.ts โ”‚ โ”‚ โ””โ”€โ”€ main.tsx โ”‚ โ”œโ”€โ”€ dist/ # Production build โ”‚ โ””โ”€โ”€ package.json โ”‚ โ”œโ”€โ”€ docs/ # Documentation โ”‚ โ”œโ”€โ”€ ARCHITECTURE.md # This file! ๐Ÿ—๏ธ โ”‚ โ”œโ”€โ”€ DEMO_TRANSACTIONS.md # Transaction tools guide โ”‚ โ”œโ”€โ”€ CIRCULAR_ECONOMY.md # Beer economy guide โ”‚ โ”œโ”€โ”€ CHAT_WALLET_INTEGRATION.md โ”‚ โ””โ”€โ”€ ... โ”‚ โ”œโ”€โ”€ .cursor/ โ”‚ โ””โ”€โ”€ mcp.json # Cursor MCP configuration โ”‚ โ”œโ”€โ”€ README.md # Main documentation โ””โ”€โ”€ package.json # Root package ``` --- ## MCP Protocol Integration ### How MCP Works in Our System ```typescript // 1. Server Setup const server = new McpServer({ name: 'coinbase-mcp-server', version: '1.0.0' }); // 2. Tool Registration (13 tools) server.registerTool( 'tool_name', { title, description, inputSchema }, async (params) => { // Tool implementation return { content: [{ type: 'text', text: result }] }; } ); // 3. Transport Layer const transport = new StdioServerTransport(); await server.connect(transport); // Now Cursor can call tools via MCP protocol! ``` ### MCP Message Flow ``` Cursor IDE (User types: "What's BTC price?") โ†“ MCP Request (JSON-RPC over stdio) { "method": "tools/call", "params": { "name": "get_spot_price", "arguments": { "currencyPair": "BTC-USD" } } } โ†“ MCP Server receives via stdio โ†“ Executes tool handler โ†“ MCP Response { "content": [{ "type": "text", "text": "Current BTC-USD price: $110,464.17" }] } โ†“ Cursor displays to user ``` --- ## Performance Characteristics ### Response Times ``` Price Query: โ”œโ”€ Coinbase API: ~200-500ms โ”œโ”€ Our processing: ~10ms โ””โ”€ Total: ~210-510ms Simulated Purchase: โ”œโ”€ Coinbase API (get price): ~200-500ms โ”œโ”€ Balance check: ~1ms โ”œโ”€ Update wallet: ~1ms โ””โ”€ Total: ~202-502ms Buy Beer with Crypto: โ”œโ”€ Coinbase API (get price): ~200-500ms โ”œโ”€ Balance check: ~1ms โ”œโ”€ Update inventory: ~1ms โ””โ”€ Total: ~202-502ms AI Chat Query: โ”œโ”€ OpenAI GPT-4: ~2-5 seconds โ”œโ”€ Tool execution: ~200-500ms per tool โ”œโ”€ Final response: ~1-3 seconds โ””โ”€ Total: ~3-9 seconds ``` ### Scalability **Current System** (In-Memory): - โœ… Handles: 1 wallet instance per server - โœ… Fast: Sub-second transactions - โŒ Limitation: Data lost on restart - โŒ Limitation: Not multi-user **Production Upgrade Path**: ```typescript // Add database for persistence import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); // Store wallets in DB async createWallet(userId: string) { return await prisma.wallet.create({ data: { userId, balances: { USD: 1000 }, transactions: [] } }); } ``` --- ## Testing Architecture ### How to Test Components ```typescript // Test 1: Coinbase Client (Real API) describe('CoinbaseClient', () => { it('should fetch real BTC price', async () => { const client = new CoinbaseClient(); const price = await client.getSpotPrice('BTC-USD'); expect(price.data.amount).toBeDefined(); expect(parseFloat(price.data.amount)).toBeGreaterThan(0); }); }); // Test 2: Demo Wallet (Simulation) describe('DemoWalletClient', () => { it('should simulate BTC purchase', async () => { const wallet = new DemoWalletClient(coinbaseClient); const tx = await wallet.simulatePurchase('USD', 'BTC', 5); expect(tx.fromCurrency).toBe('USD'); expect(tx.toCurrency).toBe('BTC'); expect(tx.fromAmount).toBe(5); expect(wallet.getBalance('USD')).toBe(995); // 1000 - 5 }); it('should buy beer if enough crypto', async () => { const wallet = new DemoWalletClient(coinbaseClient); // First buy BTC await wallet.simulatePurchase('USD', 'BTC', 5); // Then buy beer const result = await wallet.buyVirtualBeer(1, 'BTC', 5); expect(result.success).toBe(true); expect(wallet.getInventory().beers).toBe(1); }); it('should suggest buying crypto if insufficient', async () => { const wallet = new DemoWalletClient(coinbaseClient); // Try to buy beer without BTC const result = await wallet.buyVirtualBeer(1, 'BTC', 5); expect(result.success).toBe(false); expect(result.needsMoreCrypto).toBe(true); expect(result.suggestedAmount).toBe(5); }); }); ``` --- ## Key Design Decisions ### 1. Why In-Memory Storage? **Pros**: - โœ… Zero setup - no database needed - โœ… Perfect for demos/education - โœ… Fast - no I/O latency - โœ… Simple - easy to understand - โœ… Stateless - each session is fresh **Cons**: - โŒ Data lost on restart - โŒ Not suitable for production - โŒ Can't scale to multiple users **Alternative** (if needed): ```typescript // Add Redis for session storage import Redis from 'ioredis'; const redis = new Redis(); await redis.set(`wallet:${userId}`, JSON.stringify(wallet)); const wallet = JSON.parse(await redis.get(`wallet:${userId}`)); ``` ### 2. Why Not Real Blockchain? **Our Approach** (Simulation): - โœ… Instant transactions - โœ… No gas fees - โœ… Educational - โœ… Safe **Real Blockchain** (Base MCP): - โฑ๏ธ 2-5 second confirmations - ๐Ÿ’ฐ Gas fees (~$0.01-0.10) - โš ๏ธ Financial risk - ๐Ÿ” Complex setup **Best Use Case**: Start with our simulation, upgrade to real later if needed! ### 3. Why Hybrid (Real Prices + Simulated Wallet)? This gives: - ๐ŸŽ“ **Educational value** - Learn with real market data - ๐Ÿ”’ **Safety** - No financial risk - โšก **Speed** - Instant transactions - ๐Ÿ’ก **Realism** - Prices match reality - ๐ŸŽฎ **Fun** - Gamified experience --- ## Extension Points ### Easy to Add ```typescript // Add new virtual item type async buyVirtualPizza(quantity: number, currency: string) { // Same pattern as beer! const cryptoNeeded = (quantity * 15) / cryptoPrice; this.wallet.inventory.pizzas += quantity; } // Add new cryptocurrency async simulatePurchase(from, to, amount) { // Already supports ANY crypto Coinbase has! // Just needs valid pair like "DOGE-USD" } // Add portfolio analytics getPortfolioValue() { // Calculate total value using real prices let total = this.wallet.balances.USD; for (const [crypto, balance] of Object.entries(this.wallet.balances)) { if (crypto !== 'USD') { const price = await getSpotPrice(`${crypto}-USD`); total += balance * price; } } return total; } ``` ### Requires More Work ```typescript // Real trading integration import { CoinbaseAdvancedTradeClient } from 'coinbase-advanced-node'; // Needs: API keys, authentication, order management // Blockchain integration import { Wallet } from 'base-mcp'; // Needs: Private keys, network config, gas management // Multi-user system // Needs: Database, authentication, user sessions ``` --- ## Summary ### What We Built A **sophisticated educational platform** that combines: **REAL Components** (External): - โœ… Coinbase price data - โœ… MCP protocol (Anthropic) - โœ… OpenAI AI services - โœ… Market statistics - โœ… Historical data **CUSTOM Components** (Our Code): - ๐ŸŽจ Demo wallet system - ๐ŸŽจ Transaction simulator - ๐ŸŽจ Beer economy - ๐ŸŽจ Beautiful UI - ๐ŸŽจ Voice integration - ๐ŸŽจ AI orchestration **NOT Using** (Researched): - โŒ Base MCP (too complex, real money) - โŒ x402 (different use case) - โŒ Real blockchain (unnecessary risk) - โŒ Coinbase trading API (overkill) ### The Result A **perfect educational platform** that: - Teaches crypto concepts safely - Uses real market data for accuracy - Provides instant feedback - Requires zero setup - Costs nothing to run - Is production-quality code - Can upgrade to real transactions later **It's the best of all worlds!** ๐ŸŒŸ --- ## ๐Ÿ“š Further Reading - **README.md** - Project overview - **DEMO_TRANSACTIONS.md** - Transaction tools reference - **CIRCULAR_ECONOMY.md** - Beer economy guide - **CHAT_WALLET_INTEGRATION.md** - Chat integration - **MCP_SETUP_NOTES.md** - MCP configuration ## ๐Ÿ”— External References - [Model Context Protocol](https://modelcontextprotocol.io) - Official MCP docs - [Coinbase API v2](https://developers.coinbase.com/api/v2) - Public API reference - [Base MCP](https://github.com/base/base-mcp) - Real blockchain integration - [x402 Protocol](https://docs.cdp.coinbase.com/x402/mcp-server) - Micropayments - [OpenAI Platform](https://platform.openai.com/docs) - AI services --- **Built with โค๏ธ for crypto education and AI innovation!** ๐Ÿš€๐Ÿบโ‚ฟ

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Bichev/coinbase-chat-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server