Skip to main content
Glama

MCP Art Supply Store

by wspotter
index.ts63.3 kB
import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { socialMediaManager } from './social-media.js'; import { universalTools, handleUniversalTool } from './universal-tools.js'; import { vipTools, handleVIPTool } from './vip-tools.js'; // Art Supply Store MCP Server const server = new Server( { name: 'art-supply-store-assistant', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); // Mock database for demonstration const storeData = { inventory: [ { id: 'SKU001', name: 'Acrylic Paint Set (24 colors)', category: 'Paint', quantity: 45, reorderLevel: 20, price: 34.99, supplier: 'ArtCo Supplies', lastRestocked: '2025-09-28' }, { id: 'SKU002', name: 'Professional Watercolor Set', category: 'Paint', quantity: 12, reorderLevel: 15, price: 89.99, supplier: 'Premium Art Inc', lastRestocked: '2025-09-15' }, { id: 'SKU003', name: 'Canvas Panel 16x20"', category: 'Canvas', quantity: 78, reorderLevel: 30, price: 12.99, supplier: 'Canvas Warehouse', lastRestocked: '2025-10-01' }, { id: 'SKU004', name: 'Synthetic Brush Set (10pc)', category: 'Brushes', quantity: 5, reorderLevel: 10, price: 24.99, supplier: 'BrushMasters Ltd', lastRestocked: '2025-08-20' }, { id: 'SKU005', name: 'Oil Paint Starter Kit', category: 'Paint', quantity: 23, reorderLevel: 15, price: 65.99, supplier: 'ArtCo Supplies', lastRestocked: '2025-09-25' }, { id: 'SKU006', name: 'Drawing Pencil Set (12B-6H)', category: 'Drawing', quantity: 34, reorderLevel: 20, price: 18.99, supplier: 'Sketchers Supply', lastRestocked: '2025-09-30' }, { id: 'SKU007', name: 'Stretched Canvas 24x36"', category: 'Canvas', quantity: 15, reorderLevel: 10, price: 28.99, supplier: 'Canvas Warehouse', lastRestocked: '2025-09-28' }, { id: 'SKU008', name: 'Palette Knife Set (5pc)', category: 'Tools', quantity: 18, reorderLevel: 12, price: 15.99, supplier: 'ArtTools Direct', lastRestocked: '2025-09-22' }, ], customers: [ { id: 'CUST001', name: 'Sarah Martinez', email: 'sarah.m@email.com', phone: '555-0101', loyaltyPoints: 450, totalSpent: 1250.45, lastVisit: '2025-10-02', preferences: ['Watercolor', 'Brushes'] }, { id: 'CUST002', name: 'James Chen', email: 'jchen@email.com', phone: '555-0102', loyaltyPoints: 890, totalSpent: 2340.78, lastVisit: '2025-10-03', preferences: ['Oil Paint', 'Canvas'] }, { id: 'CUST003', name: 'Emily Rodriguez', email: 'emily.r@email.com', phone: '555-0103', loyaltyPoints: 230, totalSpent: 678.90, lastVisit: '2025-09-28', preferences: ['Drawing', 'Sketching'] }, { id: 'CUST004', name: 'Michael Foster', email: 'm.foster@email.com', phone: '555-0104', loyaltyPoints: 1200, totalSpent: 3890.50, lastVisit: '2025-10-01', preferences: ['Acrylic', 'Canvas', 'Brushes'] }, ], sales: [ { date: '2025-10-03', revenue: 456.78, transactions: 12, topItem: 'Acrylic Paint Set' }, { date: '2025-10-02', revenue: 623.45, transactions: 18, topItem: 'Canvas Panel 16x20"' }, { date: '2025-10-01', revenue: 389.90, transactions: 9, topItem: 'Oil Paint Starter Kit' }, { date: '2025-09-30', revenue: 712.34, transactions: 21, topItem: 'Drawing Pencil Set' }, ], suppliers: [ { id: 'SUP001', name: 'ArtCo Supplies', contact: 'orders@artcosupplies.com', phone: '1-800-ART-SUPP', leadTime: '5-7 days', minOrder: 500 }, { id: 'SUP002', name: 'Premium Art Inc', contact: 'sales@premiumart.com', phone: '1-888-PREMIUM', leadTime: '7-10 days', minOrder: 1000 }, { id: 'SUP003', name: 'Canvas Warehouse', contact: 'wholesale@canvaswarehouse.com', phone: '1-877-CANVAS-1', leadTime: '3-5 days', minOrder: 300 }, { id: 'SUP004', name: 'BrushMasters Ltd', contact: 'orders@brushmasters.com', phone: '1-866-BRUSH-99', leadTime: '5-7 days', minOrder: 250 }, ], appointments: [ { id: 'APT001', customerName: 'Sarah Martinez', service: 'Custom Framing Consultation', date: '2025-10-05', time: '14:00', duration: '30 min' }, { id: 'APT002', customerName: 'Lisa Park', service: 'Art Technique Workshop', date: '2025-10-06', time: '10:00', duration: '2 hours' }, ], employees: [ { id: 'EMP001', name: 'Alex Johnson', role: 'Store Manager', shift: 'Mon-Fri 9AM-6PM', hourlyRate: 22 }, { id: 'EMP002', name: 'Maria Santos', role: 'Sales Associate', shift: 'Tue-Sat 10AM-7PM', hourlyRate: 16 }, { id: 'EMP003', name: 'David Kim', role: 'Art Specialist', shift: 'Wed-Sun 11AM-8PM', hourlyRate: 18 }, ] }; // Tool definitions const tools = [ // INVENTORY MANAGEMENT TOOLS { name: 'check_inventory', description: 'Check current inventory levels for a specific product or category. Returns stock quantity, reorder status, and supplier information.', inputSchema: { type: 'object', properties: { search: { type: 'string', description: 'Product name, SKU, or category to search for' }, }, required: ['search'], }, }, { name: 'get_low_stock_items', description: 'Get a list of all items that are at or below their reorder level. Critical for preventing stockouts.', inputSchema: { type: 'object', properties: { category: { type: 'string', description: 'Optional: filter by category (Paint, Canvas, Brushes, Drawing, Tools)' }, }, }, }, { name: 'update_stock', description: 'Update inventory quantity after receiving shipment or doing physical count. Records the change in the system.', inputSchema: { type: 'object', properties: { sku: { type: 'string', description: 'Product SKU to update' }, quantity: { type: 'number', description: 'New quantity amount' }, reason: { type: 'string', description: 'Reason for update (received, sold, damaged, count)' }, }, required: ['sku', 'quantity', 'reason'], }, }, { name: 'search_products', description: 'Search for products by name, category, or supplier. Returns detailed product information.', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search term' }, filterBy: { type: 'string', description: 'Optional: category, supplier, or price_range' }, }, required: ['query'], }, }, // CUSTOMER MANAGEMENT TOOLS { name: 'lookup_customer', description: 'Find customer information by name, email, or phone. Returns purchase history, loyalty points, and preferences.', inputSchema: { type: 'object', properties: { identifier: { type: 'string', description: 'Customer name, email, or phone number' }, }, required: ['identifier'], }, }, { name: 'update_loyalty_points', description: 'Add or redeem loyalty points for a customer. Store policy: 1 point per $1 spent, 100 points = $10 off.', inputSchema: { type: 'object', properties: { customerId: { type: 'string', description: 'Customer ID' }, points: { type: 'number', description: 'Points to add (positive) or redeem (negative)' }, reason: { type: 'string', description: 'Reason for point adjustment' }, }, required: ['customerId', 'points', 'reason'], }, }, { name: 'get_customer_recommendations', description: 'Get personalized product recommendations based on customer purchase history and preferences.', inputSchema: { type: 'object', properties: { customerId: { type: 'string', description: 'Customer ID' }, }, required: ['customerId'], }, }, { name: 'get_top_customers', description: 'Get list of top customers by total spending or loyalty points. Useful for VIP outreach and marketing.', inputSchema: { type: 'object', properties: { sortBy: { type: 'string', description: 'Sort by: spending or loyalty_points' }, limit: { type: 'number', description: 'Number of customers to return (default: 10)' }, }, required: ['sortBy'], }, }, // SALES & ANALYTICS TOOLS { name: 'get_daily_sales', description: 'Get sales summary for a specific date including revenue, transaction count, and top-selling items.', inputSchema: { type: 'object', properties: { date: { type: 'string', description: 'Date in YYYY-MM-DD format (default: today)' }, }, }, }, { name: 'get_sales_report', description: 'Generate comprehensive sales report for a date range with trends, comparisons, and insights.', inputSchema: { type: 'object', properties: { startDate: { type: 'string', description: 'Start date in YYYY-MM-DD format' }, endDate: { type: 'string', description: 'End date in YYYY-MM-DD format' }, }, required: ['startDate', 'endDate'], }, }, { name: 'get_best_sellers', description: 'Get top-selling products by category or overall, with quantity sold and revenue generated.', inputSchema: { type: 'object', properties: { category: { type: 'string', description: 'Optional: filter by category' }, period: { type: 'string', description: 'Time period: week, month, quarter, year' }, }, required: ['period'], }, }, { name: 'calculate_profit_margin', description: 'Calculate profit margin for a product or category based on cost and selling price.', inputSchema: { type: 'object', properties: { sku: { type: 'string', description: 'Product SKU' }, costPrice: { type: 'number', description: 'Cost price per unit' }, }, required: ['sku', 'costPrice'], }, }, // SUPPLIER & ORDERING TOOLS { name: 'get_supplier_info', description: 'Get detailed supplier information including contact details, lead times, and minimum order requirements.', inputSchema: { type: 'object', properties: { supplierName: { type: 'string', description: 'Supplier name or ID' }, }, required: ['supplierName'], }, }, { name: 'create_purchase_order', description: 'Create a purchase order for restocking. Automatically suggests items below reorder level.', inputSchema: { type: 'object', properties: { supplier: { type: 'string', description: 'Supplier name' }, autoIncludeLowStock: { type: 'boolean', description: 'Automatically include low stock items from this supplier' }, customItems: { type: 'string', description: 'Optional: comma-separated SKUs to include' }, }, required: ['supplier'], }, }, { name: 'compare_supplier_prices', description: 'Compare prices and terms across suppliers for a specific product or category.', inputSchema: { type: 'object', properties: { productName: { type: 'string', description: 'Product name or category' }, }, required: ['productName'], }, }, // SCHEDULING & OPERATIONS TOOLS { name: 'check_appointments', description: 'Check scheduled appointments for a specific date or customer.', inputSchema: { type: 'object', properties: { date: { type: 'string', description: 'Date in YYYY-MM-DD format (default: today)' }, }, }, }, { name: 'book_appointment', description: 'Schedule a new appointment for custom framing, consultations, or workshops.', inputSchema: { type: 'object', properties: { customerName: { type: 'string', description: 'Customer name' }, service: { type: 'string', description: 'Service type: framing, consultation, workshop' }, date: { type: 'string', description: 'Date in YYYY-MM-DD format' }, time: { type: 'string', description: 'Time in HH:MM format' }, }, required: ['customerName', 'service', 'date', 'time'], }, }, { name: 'get_employee_schedule', description: 'Get employee schedule and shift information for staffing planning.', inputSchema: { type: 'object', properties: { date: { type: 'string', description: 'Date in YYYY-MM-DD format or day of week' }, }, }, }, { name: 'calculate_labor_cost', description: 'Calculate labor costs for a specific period based on employee hours and rates.', inputSchema: { type: 'object', properties: { startDate: { type: 'string', description: 'Start date in YYYY-MM-DD format' }, endDate: { type: 'string', description: 'End date in YYYY-MM-DD format' }, }, required: ['startDate', 'endDate'], }, }, // PRICING & PROMOTIONS TOOLS { name: 'calculate_discount', description: 'Calculate discounted price for promotions, bulk orders, or loyalty rewards.', inputSchema: { type: 'object', properties: { sku: { type: 'string', description: 'Product SKU' }, discountType: { type: 'string', description: 'Type: percentage, fixed, loyalty, bulk' }, discountValue: { type: 'number', description: 'Discount percentage or fixed amount' }, quantity: { type: 'number', description: 'Quantity for bulk pricing' }, }, required: ['sku', 'discountType', 'discountValue'], }, }, { name: 'suggest_bundle', description: 'Suggest product bundles based on frequently bought together items or complementary products.', inputSchema: { type: 'object', properties: { baseSku: { type: 'string', description: 'Base product SKU to build bundle around' }, }, required: ['baseSku'], }, }, // REPORTING & INSIGHTS TOOLS { name: 'generate_eod_report', description: 'Generate end-of-day report with sales summary, cash reconciliation needs, and action items.', inputSchema: { type: 'object', properties: { date: { type: 'string', description: 'Date in YYYY-MM-DD format (default: today)' }, }, }, }, { name: 'get_inventory_value', description: 'Calculate total inventory value at cost or retail price for financial reporting.', inputSchema: { type: 'object', properties: { valueType: { type: 'string', description: 'Calculate at: cost or retail price' }, category: { type: 'string', description: 'Optional: filter by category' }, }, required: ['valueType'], }, }, { name: 'forecast_demand', description: 'Forecast product demand based on historical sales data and seasonal trends.', inputSchema: { type: 'object', properties: { sku: { type: 'string', description: 'Product SKU' }, period: { type: 'string', description: 'Forecast period: week, month, quarter' }, }, required: ['sku', 'period'], }, }, // SOCIAL MEDIA MANAGEMENT TOOLS { name: 'post_to_social_media', description: 'Post content to Facebook and/or Instagram. Requires Meta API configuration. Can schedule posts for future publishing.', inputSchema: { type: 'object', properties: { platforms: { type: 'string', description: 'Comma-separated platforms: facebook, instagram, or both' }, message: { type: 'string', description: 'Post caption/message' }, imageUrl: { type: 'string', description: 'Optional: URL to image (required for Instagram)' }, hashtags: { type: 'string', description: 'Optional: Comma-separated hashtags (without # symbol)' }, scheduleTime: { type: 'string', description: 'Optional: Schedule for future (YYYY-MM-DD HH:MM format)' }, }, required: ['platforms', 'message'], }, }, { name: 'generate_post_ideas', description: 'Generate creative post ideas based on products, themes, or seasons. Perfect for content planning.', inputSchema: { type: 'object', properties: { theme: { type: 'string', description: 'Theme or season: fall, winter, spring, summer, sale, new_arrival, etc.' }, products: { type: 'string', description: 'Comma-separated product names to feature' }, count: { type: 'number', description: 'Number of ideas to generate (default: 5)' }, }, required: ['theme', 'products'], }, }, { name: 'schedule_weekly_posts', description: 'Create a weekly posting schedule with varied content types. Saves hours of planning time.', inputSchema: { type: 'object', properties: { startDate: { type: 'string', description: 'Week start date (YYYY-MM-DD)' }, postsPerDay: { type: 'number', description: 'Number of posts per day (1-3 recommended)' }, focusProducts: { type: 'string', description: 'Comma-separated products to feature this week' }, }, required: ['startDate', 'postsPerDay'], }, }, { name: 'get_social_analytics', description: 'Get performance analytics from Facebook and Instagram including reach, engagement, and top posts.', inputSchema: { type: 'object', properties: { platform: { type: 'string', description: 'Platform: facebook or instagram' }, period: { type: 'number', description: 'Number of days to analyze (default: 7)' }, }, required: ['platform'], }, }, { name: 'get_new_comments', description: 'Retrieve new comments from Facebook and Instagram posts for timely responses.', inputSchema: { type: 'object', properties: { sinceHours: { type: 'number', description: 'Get comments from last X hours (default: 24)' }, platform: { type: 'string', description: 'Optional: filter by facebook or instagram' }, }, }, }, { name: 'suggest_comment_reply', description: 'Get AI-powered reply suggestions for customer comments. Maintains friendly, professional tone.', inputSchema: { type: 'object', properties: { commentText: { type: 'string', description: 'The comment text to reply to' }, tone: { type: 'string', description: 'Reply tone: friendly, professional, enthusiastic (default: friendly)' }, }, required: ['commentText'], }, }, { name: 'generate_hashtags', description: 'Generate relevant hashtags for posts to maximize reach and engagement.', inputSchema: { type: 'object', properties: { postTopic: { type: 'string', description: 'Main topic or theme of the post' }, includeLocation: { type: 'boolean', description: 'Include location-based hashtags (default: true)' }, count: { type: 'number', description: 'Number of hashtags to generate (default: 15)' }, }, required: ['postTopic'], }, }, { name: 'get_instagram_story_ideas', description: 'Get creative Instagram Story ideas featuring products, behind-the-scenes, or promotions.', inputSchema: { type: 'object', properties: { occasion: { type: 'string', description: 'Occasion: daily, weekend, sale, holiday, new_product' }, products: { type: 'string', description: 'Optional: specific products to feature' }, }, required: ['occasion'], }, }, { name: 'create_product_campaign', description: 'Create a multi-post campaign to promote a specific product or collection across platforms.', inputSchema: { type: 'object', properties: { productSku: { type: 'string', description: 'Product SKU to promote' }, duration: { type: 'number', description: 'Campaign duration in days' }, platforms: { type: 'string', description: 'Platforms: facebook, instagram, or both' }, }, required: ['productSku', 'duration', 'platforms'], }, }, { name: 'analyze_post_performance', description: 'Analyze individual post performance with insights on what content performs best.', inputSchema: { type: 'object', properties: { postId: { type: 'string', description: 'Facebook or Instagram post ID' }, compareToAverage: { type: 'boolean', description: 'Compare to account average (default: true)' }, }, required: ['postId'], }, }, { name: 'auto_respond_common_questions', description: 'Enable automatic responses to frequently asked questions (hours, location, stock availability).', inputSchema: { type: 'object', properties: { enable: { type: 'boolean', description: 'Enable or disable auto-responses' }, questionTypes: { type: 'string', description: 'Types to auto-respond: hours, location, stock, pricing (comma-separated)' }, }, required: ['enable'], }, }, { name: 'track_competitor_activity', description: 'Track competitor social media activity to stay informed about market trends and pricing.', inputSchema: { type: 'object', properties: { competitors: { type: 'string', description: 'Comma-separated competitor page names or IDs' }, metrics: { type: 'string', description: 'Metrics to track: posts, engagement, promotions, products' }, }, required: ['competitors'], }, }, ...universalTools, ...vipTools ]; // Register all tools server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools }; }); // Handle tool calls server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { // INVENTORY MANAGEMENT // VIP DATASET GENERATION TOOLS case 'vip_generate_dataset': case 'vip_check_status': case 'vip_list_datasets': case 'vip_get_dataset_info': case 'vip_stop_pipeline': case 'vip_validate_config': case 'vip_health_check': { const result = await handleVIPTool(name, args); return { content: [{ type: 'text', text: result }] }; } // UNIVERSAL DAILY TASK TOOLS case 'create_task': case 'list_tasks': case 'complete_task': case 'update_task': case 'get_daily_agenda': case 'schedule_event': case 'list_upcoming_events': case 'set_reminder': case 'get_today_schedule': case 'create_note': case 'search_notes': case 'tag_note': case 'log_expense': case 'get_expense_summary': case 'categorize_expenses': case 'generate_daily_summary': case 'export_data': case 'create_alert': case 'list_alerts': { const result = await handleUniversalTool(name, args); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } case 'check_inventory': { const search = String(args?.search || '').toLowerCase(); const results = storeData.inventory.filter(item => item.name.toLowerCase().includes(search) || item.id.toLowerCase().includes(search) || item.category.toLowerCase().includes(search) ); return { content: [{ type: 'text', text: results.length > 0 ? `Found ${results.length} item(s):\n\n${results.map(item => `${item.name} (${item.id})\n- Category: ${item.category}\n- Stock: ${item.quantity} units${item.quantity <= item.reorderLevel ? ' ⚠️ LOW STOCK' : ''}\n- Price: $${item.price}\n- Supplier: ${item.supplier}\n- Last Restocked: ${item.lastRestocked}` ).join('\n\n')}` : `No items found matching "${args?.search}"` }] }; } case 'get_low_stock_items': { const category = args?.category ? String(args.category) : null; let lowStockItems = storeData.inventory.filter(item => item.quantity <= item.reorderLevel); if (category) { lowStockItems = lowStockItems.filter(item => item.category.toLowerCase() === category.toLowerCase()); } return { content: [{ type: 'text', text: lowStockItems.length > 0 ? `⚠️ ${lowStockItems.length} item(s) need reordering:\n\n${lowStockItems.map(item => `${item.name} (${item.id})\n- Current: ${item.quantity} | Reorder Level: ${item.reorderLevel}\n- Need to order: ${item.reorderLevel * 2 - item.quantity} units\n- Supplier: ${item.supplier}` ).join('\n\n')}` : '✅ All items are adequately stocked!' }] }; } case 'update_stock': { const sku = String(args?.sku || ''); const quantity = Number(args?.quantity || 0); const reason = String(args?.reason || 'manual update'); const item = storeData.inventory.find(i => i.id === sku); if (!item) { return { content: [{ type: 'text', text: `❌ Product ${sku} not found` }] }; } const oldQty = item.quantity; item.quantity = quantity; const diff = quantity - oldQty; return { content: [{ type: 'text', text: `✅ Stock updated for ${item.name}\n- Previous: ${oldQty} units\n- New: ${quantity} units\n- Change: ${diff > 0 ? '+' : ''}${diff} units\n- Reason: ${reason}\n- ${quantity <= item.reorderLevel ? '⚠️ Now below reorder level!' : 'Stock level OK'}` }] }; } case 'search_products': { const query = String(args?.query || '').toLowerCase(); const filterBy = args?.filterBy ? String(args.filterBy) : null; let results = storeData.inventory.filter(item => item.name.toLowerCase().includes(query) || item.category.toLowerCase().includes(query) ); return { content: [{ type: 'text', text: `Found ${results.length} product(s):\n\n${results.map(item => `📦 ${item.name}\n- SKU: ${item.id} | Price: $${item.price}\n- Category: ${item.category} | Stock: ${item.quantity}\n- Supplier: ${item.supplier}` ).join('\n\n')}` }] }; } // CUSTOMER MANAGEMENT case 'lookup_customer': { const identifier = String(args?.identifier || '').toLowerCase(); const customer = storeData.customers.find(c => c.name.toLowerCase().includes(identifier) || c.email.toLowerCase().includes(identifier) || c.phone.includes(identifier) || c.id.toLowerCase() === identifier ); if (!customer) { return { content: [{ type: 'text', text: `❌ Customer not found: "${args?.identifier}"` }] }; } return { content: [{ type: 'text', text: `👤 ${customer.name} (${customer.id})\n\n📧 ${customer.email}\n📱 ${customer.phone}\n\n💰 Total Spent: $${customer.totalSpent.toFixed(2)}\n⭐ Loyalty Points: ${customer.loyaltyPoints} (≈ $${(customer.loyaltyPoints / 10).toFixed(2)} credit)\n📅 Last Visit: ${customer.lastVisit}\n🎨 Preferences: ${customer.preferences.join(', ')}` }] }; } case 'update_loyalty_points': { const customerId = String(args?.customerId || ''); const points = Number(args?.points || 0); const reason = String(args?.reason || 'adjustment'); const customer = storeData.customers.find(c => c.id === customerId); if (!customer) { return { content: [{ type: 'text', text: `❌ Customer ${customerId} not found` }] }; } const oldPoints = customer.loyaltyPoints; customer.loyaltyPoints += points; return { content: [{ type: 'text', text: `✅ Loyalty points updated for ${customer.name}\n- Previous: ${oldPoints} points\n- Change: ${points > 0 ? '+' : ''}${points} points\n- New Balance: ${customer.loyaltyPoints} points (≈ $${(customer.loyaltyPoints / 10).toFixed(2)} credit)\n- Reason: ${reason}` }] }; } case 'get_customer_recommendations': { const customerId = String(args?.customerId || ''); const customer = storeData.customers.find(c => c.id === customerId); if (!customer) { return { content: [{ type: 'text', text: `❌ Customer ${customerId} not found` }] }; } const recommendations = storeData.inventory.filter(item => customer.preferences.some(pref => item.name.toLowerCase().includes(pref.toLowerCase()) || item.category.toLowerCase().includes(pref.toLowerCase()) ) ).slice(0, 5); return { content: [{ type: 'text', text: `🎯 Personalized recommendations for ${customer.name}:\n\nBased on preferences: ${customer.preferences.join(', ')}\n\n${recommendations.map(item => `• ${item.name} - $${item.price}\n ${item.quantity} in stock` ).join('\n')}` }] }; } case 'get_top_customers': { const sortBy = String(args?.sortBy || 'spending'); const limit = Number(args?.limit || 10); const sorted = [...storeData.customers].sort((a, b) => sortBy === 'loyalty_points' ? b.loyaltyPoints - a.loyaltyPoints : b.totalSpent - a.totalSpent ).slice(0, limit); return { content: [{ type: 'text', text: `🏆 Top ${limit} Customers by ${sortBy === 'loyalty_points' ? 'Loyalty Points' : 'Total Spending'}:\n\n${sorted.map((c, i) => `${i + 1}. ${c.name}\n ${sortBy === 'loyalty_points' ? `${c.loyaltyPoints} points` : `$${c.totalSpent.toFixed(2)} spent`} | Last visit: ${c.lastVisit}` ).join('\n\n')}` }] }; } // SALES & ANALYTICS case 'get_daily_sales': { const date = String(args?.date || '2025-10-03'); const salesData = storeData.sales.find(s => s.date === date); if (!salesData) { return { content: [{ type: 'text', text: `No sales data found for ${date}` }] }; } return { content: [{ type: 'text', text: `📊 Sales Report for ${salesData.date}\n\n💵 Revenue: $${salesData.revenue.toFixed(2)}\n🛒 Transactions: ${salesData.transactions}\n📈 Avg Transaction: $${(salesData.revenue / salesData.transactions).toFixed(2)}\n🏆 Top Seller: ${salesData.topItem}` }] }; } case 'get_sales_report': { const startDate = String(args?.startDate || ''); const endDate = String(args?.endDate || ''); const periodSales = storeData.sales.filter(s => s.date >= startDate && s.date <= endDate); const totalRevenue = periodSales.reduce((sum, s) => sum + s.revenue, 0); const totalTransactions = periodSales.reduce((sum, s) => sum + s.transactions, 0); return { content: [{ type: 'text', text: `📊 Sales Report: ${startDate} to ${endDate}\n\n💰 Total Revenue: $${totalRevenue.toFixed(2)}\n🛒 Total Transactions: ${totalTransactions}\n📈 Average Transaction: $${(totalRevenue / totalTransactions).toFixed(2)}\n📅 Days in Period: ${periodSales.length}\n📊 Daily Average: $${(totalRevenue / periodSales.length).toFixed(2)}` }] }; } case 'get_best_sellers': { const category = args?.category ? String(args.category) : null; const period = String(args?.period || 'week'); let items = storeData.inventory; if (category) { items = items.filter(i => i.category.toLowerCase() === category.toLowerCase()); } const bestSellers = items.sort((a, b) => b.price - a.price).slice(0, 5); return { content: [{ type: 'text', text: `🏆 Best Sellers${category ? ` in ${category}` : ''} (${period}):\n\n${bestSellers.map((item, i) => `${i + 1}. ${item.name}\n Price: $${item.price} | In stock: ${item.quantity}` ).join('\n\n')}` }] }; } case 'calculate_profit_margin': { const sku = String(args?.sku || ''); const costPrice = Number(args?.costPrice || 0); const item = storeData.inventory.find(i => i.id === sku); if (!item) { return { content: [{ type: 'text', text: `❌ Product ${sku} not found` }] }; } const profit = item.price - costPrice; const margin = (profit / item.price) * 100; return { content: [{ type: 'text', text: `💰 Profit Analysis: ${item.name}\n\n- Selling Price: $${item.price}\n- Cost Price: $${costPrice.toFixed(2)}\n- Profit per Unit: $${profit.toFixed(2)}\n- Profit Margin: ${margin.toFixed(1)}%\n- Potential Revenue (current stock): $${(item.quantity * profit).toFixed(2)}` }] }; } // SUPPLIER & ORDERING case 'get_supplier_info': { const supplierName = String(args?.supplierName || '').toLowerCase(); const supplier = storeData.suppliers.find(s => s.name.toLowerCase().includes(supplierName) || s.id.toLowerCase() === supplierName ); if (!supplier) { return { content: [{ type: 'text', text: `❌ Supplier not found: "${args?.supplierName}"` }] }; } const supplierProducts = storeData.inventory.filter(i => i.supplier === supplier.name); return { content: [{ type: 'text', text: `🏢 ${supplier.name} (${supplier.id})\n\n📧 ${supplier.contact}\n📱 ${supplier.phone}\n⏱️ Lead Time: ${supplier.leadTime}\n💵 Minimum Order: $${supplier.minOrder}\n\n📦 Products from this supplier: ${supplierProducts.length}\n${supplierProducts.slice(0, 5).map(p => `• ${p.name}`).join('\n')}` }] }; } case 'create_purchase_order': { const supplier = String(args?.supplier || ''); const autoInclude = Boolean(args?.autoIncludeLowStock); const supplierInfo = storeData.suppliers.find(s => s.name.toLowerCase().includes(supplier.toLowerCase())); if (!supplierInfo) { return { content: [{ type: 'text', text: `❌ Supplier not found: "${supplier}"` }] }; } const supplierProducts = storeData.inventory.filter(i => i.supplier === supplierInfo.name); const lowStock = autoInclude ? supplierProducts.filter(i => i.quantity <= i.reorderLevel) : []; const orderTotal = lowStock.reduce((sum, item) => sum + (item.price * (item.reorderLevel * 2 - item.quantity)), 0); return { content: [{ type: 'text', text: `📝 Purchase Order Created\n\n🏢 Supplier: ${supplierInfo.name}\n📅 Date: ${new Date().toISOString().split('T')[0]}\n⏱️ Expected Delivery: ${supplierInfo.leadTime}\n\n${lowStock.length > 0 ? `Items to Order:\n${lowStock.map(item => `• ${item.name} (${item.id})\n Order Qty: ${item.reorderLevel * 2 - item.quantity} | Est. Cost: $${(item.price * (item.reorderLevel * 2 - item.quantity) * 0.6).toFixed(2)}` ).join('\n\n')}\n\n💰 Estimated Total: $${(orderTotal * 0.6).toFixed(2)}` : 'No items below reorder level for this supplier.'}` }] }; } case 'compare_supplier_prices': { const productName = String(args?.productName || '').toLowerCase(); const products = storeData.inventory.filter(i => i.name.toLowerCase().includes(productName) || i.category.toLowerCase().includes(productName) ); if (products.length === 0) { return { content: [{ type: 'text', text: `No products found matching "${args?.productName}"` }] }; } const supplierMap = new Map(); products.forEach(p => { if (!supplierMap.has(p.supplier)) { supplierMap.set(p.supplier, []); } supplierMap.get(p.supplier).push(p); }); return { content: [{ type: 'text', text: `💲 Price Comparison for "${args?.productName}":\n\n${Array.from(supplierMap.entries()).map(([supplier, items]) => { const supplierInfo = storeData.suppliers.find(s => s.name === supplier); return `${supplier}:\n${items.map((item: any) => `• ${item.name} - $${item.price}`).join('\n')}\nLead Time: ${supplierInfo?.leadTime || 'N/A'}`; }).join('\n\n')}` }] }; } // SCHEDULING & OPERATIONS case 'check_appointments': { const date = String(args?.date || new Date().toISOString().split('T')[0]); const appointments = storeData.appointments.filter(a => a.date === date); return { content: [{ type: 'text', text: appointments.length > 0 ? `📅 Appointments for ${date}:\n\n${appointments.map(apt => `⏰ ${apt.time} - ${apt.service}\n👤 Customer: ${apt.customerName}\n⏱️ Duration: ${apt.duration}` ).join('\n\n')}` : `No appointments scheduled for ${date}` }] }; } case 'book_appointment': { const customerName = String(args?.customerName || ''); const service = String(args?.service || ''); const date = String(args?.date || ''); const time = String(args?.time || ''); const newApt = { id: `APT${String(storeData.appointments.length + 1).padStart(3, '0')}`, customerName, service, date, time, duration: service.toLowerCase().includes('workshop') ? '2 hours' : '30 min' }; storeData.appointments.push(newApt); return { content: [{ type: 'text', text: `✅ Appointment Booked!\n\n📅 ${date} at ${time}\n👤 ${customerName}\n🎨 Service: ${service}\n⏱️ Duration: ${newApt.duration}\n🎫 Confirmation: ${newApt.id}` }] }; } case 'get_employee_schedule': { const date = String(args?.date || new Date().toLocaleDateString('en-US', { weekday: 'long' })); return { content: [{ type: 'text', text: `👥 Employee Schedule:\n\n${storeData.employees.map(emp => `${emp.name} - ${emp.role}\n📅 ${emp.shift}\n💵 Rate: $${emp.hourlyRate}/hr` ).join('\n\n')}` }] }; } case 'calculate_labor_cost': { const startDate = String(args?.startDate || ''); const endDate = String(args?.endDate || ''); const days = Math.ceil((new Date(endDate).getTime() - new Date(startDate).getTime()) / (1000 * 60 * 60 * 24)); const totalCost = storeData.employees.reduce((sum, emp) => sum + (emp.hourlyRate * 40 * days / 7), 0); return { content: [{ type: 'text', text: `💰 Labor Cost Analysis\n📅 Period: ${startDate} to ${endDate} (${days} days)\n\n${storeData.employees.map(emp => `${emp.name}: $${(emp.hourlyRate * 40 * days / 7).toFixed(2)}` ).join('\n')}\n\n💵 Total Labor Cost: $${totalCost.toFixed(2)}\n📊 Daily Average: $${(totalCost / days).toFixed(2)}` }] }; } // PRICING & PROMOTIONS case 'calculate_discount': { const sku = String(args?.sku || ''); const discountType = String(args?.discountType || 'percentage'); const discountValue = Number(args?.discountValue || 0); const quantity = Number(args?.quantity || 1); const item = storeData.inventory.find(i => i.id === sku); if (!item) { return { content: [{ type: 'text', text: `❌ Product ${sku} not found` }] }; } let finalPrice = item.price; let discount = 0; switch (discountType) { case 'percentage': discount = item.price * (discountValue / 100); finalPrice = item.price - discount; break; case 'fixed': discount = discountValue; finalPrice = item.price - discount; break; case 'loyalty': discount = discountValue / 10; finalPrice = item.price - discount; break; case 'bulk': if (quantity >= 5) { discount = item.price * 0.15; finalPrice = item.price - discount; } break; } return { content: [{ type: 'text', text: `💲 Price Calculation: ${item.name}\n\n- Original Price: $${item.price}\n- Discount Type: ${discountType}\n- Discount Amount: $${discount.toFixed(2)}\n- Final Price: $${finalPrice.toFixed(2)}\n- Quantity: ${quantity}\n- Total: $${(finalPrice * quantity).toFixed(2)}` }] }; } case 'suggest_bundle': { const baseSku = String(args?.baseSku || ''); const baseItem = storeData.inventory.find(i => i.id === baseSku); if (!baseItem) { return { content: [{ type: 'text', text: `❌ Product ${baseSku} not found` }] }; } const complementary = storeData.inventory .filter(i => i.category === baseItem.category || i.id !== baseSku) .slice(0, 3); const bundlePrice = baseItem.price + complementary.reduce((sum, item) => sum + item.price, 0); const bundleDiscount = bundlePrice * 0.15; return { content: [{ type: 'text', text: `🎁 Suggested Bundle:\n\n📦 Base Item:\n• ${baseItem.name} - $${baseItem.price}\n\n➕ Add to Bundle:\n${complementary.map(item => `• ${item.name} - $${item.price}` ).join('\n')}\n\n💰 Bundle Price:\n- Individual Total: $${bundlePrice.toFixed(2)}\n- Bundle Discount (15%): -$${bundleDiscount.toFixed(2)}\n- Bundle Price: $${(bundlePrice - bundleDiscount).toFixed(2)}\n💵 Customer Saves: $${bundleDiscount.toFixed(2)}` }] }; } // REPORTING & INSIGHTS case 'generate_eod_report': { const date = String(args?.date || '2025-10-03'); const salesData = storeData.sales.find(s => s.date === date); const lowStock = storeData.inventory.filter(i => i.quantity <= i.reorderLevel); const appointments = storeData.appointments.filter(a => a.date === date); return { content: [{ type: 'text', text: `📋 End of Day Report - ${date}\n\n💰 SALES SUMMARY:\n- Revenue: $${salesData?.revenue.toFixed(2) || '0.00'}\n- Transactions: ${salesData?.transactions || 0}\n- Avg Transaction: $${salesData ? (salesData.revenue / salesData.transactions).toFixed(2) : '0.00'}\n\n⚠️ ACTION ITEMS:\n- ${lowStock.length} items need reordering\n- ${appointments.length} appointments completed\n\n📊 KEY METRICS:\n- Top Seller: ${salesData?.topItem || 'N/A'}\n- Inventory Alerts: ${lowStock.length}\n\n✅ CLOSING TASKS:\n□ Count cash drawer\n□ Review low stock report\n□ Confirm tomorrow's appointments\n□ Lock up and set alarm` }] }; } case 'get_inventory_value': { const valueType = String(args?.valueType || 'retail'); const category = args?.category ? String(args.category) : null; let items = storeData.inventory; if (category) { items = items.filter(i => i.category.toLowerCase() === category.toLowerCase()); } const retailValue = items.reduce((sum, item) => sum + (item.price * item.quantity), 0); const costValue = retailValue * 0.6; // Assume 40% markup return { content: [{ type: 'text', text: `💎 Inventory Valuation${category ? ` - ${category}` : ''}\n\n📦 Total Items: ${items.length}\n📊 Total Units: ${items.reduce((sum, i) => sum + i.quantity, 0)}\n\n💰 Value at Cost: $${costValue.toFixed(2)}\n💵 Value at Retail: $${retailValue.toFixed(2)}\n📈 Potential Profit: $${(retailValue - costValue).toFixed(2)}` }] }; } case 'forecast_demand': { const sku = String(args?.sku || ''); const period = String(args?.period || 'month'); const item = storeData.inventory.find(i => i.id === sku); if (!item) { return { content: [{ type: 'text', text: `❌ Product ${sku} not found` }] }; } const baselineSales = 50; const periodMultiplier = period === 'week' ? 0.25 : period === 'month' ? 1 : 3; const forecast = Math.round(baselineSales * periodMultiplier); return { content: [{ type: 'text', text: `📈 Demand Forecast: ${item.name}\n\n📅 Period: Next ${period}\n📊 Forecasted Sales: ~${forecast} units\n📦 Current Stock: ${item.quantity} units\n\n${item.quantity < forecast ? `⚠️ WARNING: Current stock may not meet demand!\n💡 Recommended order: ${forecast - item.quantity + item.reorderLevel} units` : '✅ Current stock sufficient for forecasted demand'}` }] }; } // SOCIAL MEDIA MANAGEMENT case 'post_to_social_media': { if (!socialMediaManager.isConfigured()) { return { content: [{ type: 'text', text: `⚠️ Social media not configured yet!\n\nTo use this feature:\n1. Create a Facebook Business account\n2. Create a Facebook App\n3. Get your access tokens\n4. Add them to your .env file\n\nSee FACEBOOK_INSTAGRAM_SETUP.md for detailed instructions.` }] }; } const platforms = String(args?.platforms || 'facebook').toLowerCase().split(',').map(p => p.trim()); const message = String(args?.message || ''); const imageUrl = args?.imageUrl ? String(args.imageUrl) : undefined; const hashtags = args?.hashtags ? String(args.hashtags).split(',').map(h => h.trim()) : undefined; const scheduleTime = args?.scheduleTime ? String(args.scheduleTime) : undefined; const results = []; for (const platform of platforms) { if (platform === 'facebook' || platform === 'both') { const result = await socialMediaManager.postToFacebook({ platform: 'facebook', message, imageUrl, scheduledTime: scheduleTime }); results.push(result); } if (platform === 'instagram' || platform === 'both') { const result = await socialMediaManager.postToInstagram({ platform: 'instagram', message, imageUrl, hashtags }); results.push(result); } } const successCount = results.filter(r => r.success).length; const failedResults = results.filter(r => !r.success); return { content: [{ type: 'text', text: `📱 Social Media Post Results\n\n✅ ${successCount}/${results.length} successful\n\n${results.map(r => r.success ? `✓ ${r.platform}: Posted${r.scheduledTime ? ` (scheduled for ${r.scheduledTime})` : ''}\n Post ID: ${r.postId}` : `✗ ${r.platform}: Failed - ${r.error}` ).join('\n\n')}${failedResults.length > 0 ? '\n\n💡 Tip: Check your API tokens and permissions if posts failed.' : ''}` }] }; } case 'generate_post_ideas': { const theme = String(args?.theme || ''); const productsArg = String(args?.products || ''); const count = Number(args?.count || 5); const products = productsArg.split(',').map(p => p.trim()); const ideas = socialMediaManager.generatePostIdeas(theme, products); return { content: [{ type: 'text', text: `💡 Post Ideas - ${theme}\n\n${ideas.slice(0, count).map((idea, i) => `${i + 1}. ${idea}` ).join('\n\n')}\n\n✨ Pro tip: Customize these ideas with your store's personality and current promotions!` }] }; } case 'schedule_weekly_posts': { const startDate = String(args?.startDate || ''); const postsPerDay = Number(args?.postsPerDay || 1); const focusProducts = String(args?.focusProducts || ''); const products = focusProducts ? focusProducts.split(',').map(p => p.trim()) : ['Acrylic Paint', 'Brushes', 'Canvas']; const postTypes = ['product_feature', 'behind_the_scenes', 'customer_spotlight', 'tip_of_the_day', 'promotion']; const schedule = []; const start = new Date(startDate); for (let day = 0; day < 7; day++) { const currentDate = new Date(start); currentDate.setDate(start.getDate() + day); const dateStr = currentDate.toISOString().split('T')[0]; const dayName = currentDate.toLocaleDateString('en-US', { weekday: 'long' }); for (let post = 0; post < postsPerDay; post++) { const postType = postTypes[Math.floor(Math.random() * postTypes.length)]; const product = products[Math.floor(Math.random() * products.length)]; schedule.push({ date: dateStr, day: dayName, time: post === 0 ? '10:00 AM' : post === 1 ? '2:00 PM' : '6:00 PM', type: postType, suggestion: `${postType.replace('_', ' ').toUpperCase()}: Feature ${product}` }); } } return { content: [{ type: 'text', text: `📅 Weekly Posting Schedule\n📍 Week of ${startDate}\n\n${schedule.map(s => `${s.day}, ${s.date} @ ${s.time}\n ${s.suggestion}` ).join('\n\n')}\n\n💡 Use 'generate_post_ideas' for specific content, then 'post_to_social_media' to publish!` }] }; } case 'get_social_analytics': { if (!socialMediaManager.isConfigured()) { return { content: [{ type: 'text', text: `⚠️ Social media not configured. See FACEBOOK_INSTAGRAM_SETUP.md for setup instructions.` }] }; } const platform = String(args?.platform || 'facebook'); const period = Number(args?.period || 7); try { if (platform.toLowerCase() === 'facebook') { const analytics = await socialMediaManager.getFacebookAnalytics(period); return { content: [{ type: 'text', text: `📊 Facebook Analytics - ${analytics.period}\n\n📈 Performance Metrics:\n 👥 Reach: ${analytics.metrics.reach.toLocaleString()}\n 👁️ Impressions: ${analytics.metrics.impressions.toLocaleString()}\n 💬 Engagement: ${analytics.metrics.engagement.toLocaleString()}\n ⭐ Followers: ${analytics.metrics.followers.toLocaleString()}\n\n🏆 Top Posts:\n${analytics.topPosts.map((post, i) => `${i + 1}. ${post.content}\n ❤️ ${post.likes} | 💬 ${post.comments} | 🔄 ${post.shares}` ).join('\n\n')}\n\n💡 Insight: Post more content like your top performers to boost engagement!` }] }; } else { return { content: [{ type: 'text', text: `📊 Instagram Analytics coming soon! Currently only Facebook analytics are available.` }] }; } } catch (error: any) { return { content: [{ type: 'text', text: `❌ Failed to fetch analytics: ${error.message}` }] }; } } case 'get_new_comments': { if (!socialMediaManager.isConfigured()) { return { content: [{ type: 'text', text: `⚠️ Social media not configured. See FACEBOOK_INSTAGRAM_SETUP.md for setup instructions.` }] }; } const sinceHours = Number(args?.sinceHours || 24); try { const comments = await socialMediaManager.getFacebookComments(sinceHours); if (comments.length === 0) { return { content: [{ type: 'text', text: `✅ No new comments in the last ${sinceHours} hours. All caught up!` }] }; } return { content: [{ type: 'text', text: `💬 New Comments (Last ${sinceHours} hours)\n\n${comments.map((comment, i) => `${i + 1}. From ${comment.from} on ${comment.platform}\n "${comment.text}"\n 🕐 ${new Date(comment.timestamp).toLocaleString()}` ).join('\n\n')}\n\n💡 Use 'suggest_comment_reply' to get AI-powered reply suggestions!` }] }; } catch (error: any) { return { content: [{ type: 'text', text: `❌ Failed to fetch comments: ${error.message}` }] }; } } case 'suggest_comment_reply': { const commentText = String(args?.commentText || ''); const tone = String(args?.tone || 'friendly'); if (!commentText) { return { content: [{ type: 'text', text: `❌ Please provide the comment text to reply to.` }] }; } const suggestions = socialMediaManager.generateCommentReplySuggestions(commentText); return { content: [{ type: 'text', text: `💬 Reply Suggestions (${tone} tone)\n\nOriginal comment: "${commentText}"\n\n${suggestions.map((suggestion, i) => `${i + 1}. ${suggestion}` ).join('\n\n')}\n\n✨ Feel free to customize these replies to match your store's voice!` }] }; } case 'generate_hashtags': { const postTopic = String(args?.postTopic || ''); const includeLocation = Boolean(args?.includeLocation ?? true); const count = Number(args?.count || 15); if (!postTopic) { return { content: [{ type: 'text', text: `❌ Please provide a post topic to generate hashtags.` }] }; } const hashtags = socialMediaManager.generateHashtags(postTopic, includeLocation); return { content: [{ type: 'text', text: `#️⃣ Hashtag Suggestions for "${postTopic}"\n\n${hashtags.slice(0, count).map(tag => `#${tag}`).join(' ')}\n\n📋 Copy-paste ready: ${hashtags.slice(0, count).map(tag => `#${tag}`).join(' ')}\n\n💡 Pro tip: Use 10-15 hashtags per post for maximum reach without looking spammy!` }] }; } case 'get_instagram_story_ideas': { const occasion = String(args?.occasion || 'daily'); const productsArg = args?.products ? String(args.products) : ''; const storyIdeas = [ `📸 Behind the counter: Show off new ${productsArg || 'art supplies'} that just arrived!`, `🎨 Quick tip: Demo how to use ${productsArg || 'one of your products'} in 15 seconds`, `❓ Poll: "What's your favorite art medium?" with product stickers`, `⏰ Countdown sticker: "${occasion}" sale starts in...`, `🌟 Customer spotlight: Share a tagged photo of customer artwork (with permission)`, `💯 This or That: Show two products and let followers vote`, `🎯 Link sticker: "New blog post: Top 5 ${productsArg || 'art supplies'} for beginners"`, `📦 Unboxing: Quick reveal of what's in today's shipment` ]; return { content: [{ type: 'text', text: `📱 Instagram Story Ideas - ${occasion}\n\n${storyIdeas.map((idea, i) => `${i + 1}. ${idea}` ).join('\n\n')}\n\n✨ Remember: Stories are temporary, so have fun and be authentic!` }] }; } case 'create_product_campaign': { const productSku = String(args?.productSku || ''); const duration = Number(args?.duration || 7); const platforms = String(args?.platforms || 'both'); const product = storeData.inventory.find(p => p.id === productSku); if (!product) { return { content: [{ type: 'text', text: `❌ Product ${productSku} not found in inventory.` }] }; } const campaignPosts = [ { day: 1, type: 'Announcement', content: `🎉 Introducing: ${product.name}! Perfect for ${product.category.toLowerCase()} artists. $${product.price} - Available now!` }, { day: 3, type: 'Feature Highlight', content: `✨ Why ${product.name}? Let us show you what makes this ${product.category} essential for your creative toolkit!` }, { day: 5, type: 'Customer Testimonial', content: `⭐ "Love the ${product.name}!" - Hear what our customers are saying about this amazing product!` }, { day: duration, type: 'Last Chance', content: `⏰ Don't miss out! Get your ${product.name} today while supplies last. Only ${product.quantity} in stock!` } ]; return { content: [{ type: 'text', text: `🎯 Product Campaign: ${product.name}\n📅 Duration: ${duration} days\n📱 Platforms: ${platforms}\n💰 Price: $${product.price}\n\n📋 Campaign Schedule:\n\n${campaignPosts.filter(p => p.day <= duration).map(post => `Day ${post.day} - ${post.type}\n${post.content}` ).join('\n\n')}\n\n💡 Use 'post_to_social_media' to publish each post, and 'generate_hashtags' for maximum reach!` }] }; } case 'analyze_post_performance': { const postId = String(args?.postId || ''); const compareToAverage = Boolean(args?.compareToAverage ?? true); if (!postId) { return { content: [{ type: 'text', text: `❌ Please provide a post ID to analyze.` }] }; } // Mock analysis (real implementation would call Meta Graph API) const mockAnalysis = { postId, reach: 2340, impressions: 3120, engagement: 187, likes: 156, comments: 23, shares: 8, engagementRate: 8.0, accountAverage: { reach: 1850, engagementRate: 5.5 } }; const performance = mockAnalysis.engagementRate > mockAnalysis.accountAverage.engagementRate ? '📈 Above' : '📉 Below'; return { content: [{ type: 'text', text: `📊 Post Performance Analysis\n🆔 Post ID: ${postId}\n\n📈 Metrics:\n 👥 Reach: ${mockAnalysis.reach.toLocaleString()}\n 👁️ Impressions: ${mockAnalysis.impressions.toLocaleString()}\n 💬 Engagement: ${mockAnalysis.engagement} (${mockAnalysis.engagementRate}%)\n ❤️ Likes: ${mockAnalysis.likes}\n 💬 Comments: ${mockAnalysis.comments}\n 🔄 Shares: ${mockAnalysis.shares}\n\n${compareToAverage ? `📊 vs Account Average:\n ${performance} average (${mockAnalysis.engagementRate}% vs ${mockAnalysis.accountAverage.engagementRate}%)\n Reach ${mockAnalysis.reach > mockAnalysis.accountAverage.reach ? '+' : ''}${((mockAnalysis.reach / mockAnalysis.accountAverage.reach - 1) * 100).toFixed(1)}%\n\n` : ''}💡 Insight: ${mockAnalysis.engagementRate > 7 ? 'Great post! Create more content like this.' : 'Try experimenting with different content types or posting times.'}` }] }; } case 'auto_respond_common_questions': { const enable = Boolean(args?.enable ?? false); const questionTypes = String(args?.questionTypes || 'hours,location,stock'); const types = questionTypes.split(',').map(t => t.trim()); return { content: [{ type: 'text', text: `🤖 Auto-Response Settings ${enable ? 'ENABLED' : 'DISABLED'}\n\n${enable ? '✅ Will auto-respond to:\n' + types.map(type => ` • ${type.charAt(0).toUpperCase() + type.slice(1)} questions` ).join('\n') : '❌ Auto-responses are disabled'}\n\n⚙️ Note: Auto-responses help provide quick answers, but always review and personalize when possible!\n\n💡 This is a mock feature. In production, this would integrate with Facebook's Messenger API for automated responses.` }] }; } case 'track_competitor_activity': { const competitors = String(args?.competitors || ''); const metrics = String(args?.metrics || 'posts,engagement'); if (!competitors) { return { content: [{ type: 'text', text: `❌ Please provide competitor page names to track.` }] }; } const competitorList = competitors.split(',').map(c => c.trim()); const metricsList = metrics.split(',').map(m => m.trim()); // Mock competitor data const mockData = competitorList.map(comp => ({ name: comp, postsThisWeek: Math.floor(Math.random() * 10) + 3, avgEngagement: Math.floor(Math.random() * 200) + 50, recentPromotion: Math.random() > 0.5 ? 'Yes - Sale on brushes' : 'No recent promotions' })); return { content: [{ type: 'text', text: `🔍 Competitor Activity Tracking\n📊 Metrics: ${metricsList.join(', ')}\n\n${mockData.map(comp => `📍 ${comp.name}\n 📝 Posts this week: ${comp.postsThisWeek}\n 💬 Avg engagement: ${comp.avgEngagement}\n 🎯 Promotions: ${comp.recentPromotion}` ).join('\n\n')}\n\n💡 Note: This is a demonstration feature. In production, this would track public competitor pages to help you stay competitive.` }] }; } default: throw new Error(`Unknown tool: ${name}`); } } catch (error: any) { return { content: [{ type: 'text', text: `❌ Error executing ${name}: ${error.message}` }], isError: true, }; } }); // Start the server const transport = new StdioServerTransport(); server.connect(transport).catch((err) => { console.error('Fatal error in MCP server:', err); process.exit(1); });

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/wspotter/mcpart'

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