UNPKG

smartlead-mcp-by-leadmagic

Version:

πŸ’œ The Premier Model Context Protocol Server for SmartLead's Cold Email Automation Platform - Complete API coverage with 116+ tools for campaign management, lead tracking, smart delivery, and analytics. Beautiful purple-gradient installer, zero-config set

378 lines β€’ 23.3 kB
#!/usr/bin/env node import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /** * πŸ’œ SmartLead MCP Server - Beautiful Interactive Installer * * The most beautiful, user-friendly MCP installer ever created! * Features stunning purple gradients, smooth animations, and zero-config setup. * * @author LeadMagic Team * @version 1.6.1 */ import fs from 'fs'; import { Box, Text, useApp, useInput } from 'ink'; import BigText from 'ink-big-text'; import Gradient from 'ink-gradient'; import Link from 'ink-link'; import SelectInput from 'ink-select-input'; import Spinner from 'ink-spinner'; import TextInput from 'ink-text-input'; import os from 'os'; import path from 'path'; import { useEffect, useState } from 'react'; import { SmartLeadClient, SmartLeadError } from './client/index.js'; // ===== UTILITIES ===== const getConfigPaths = () => { const platform = process.platform; const home = os.homedir(); const paths = { darwin: { claude: path.join(home, 'Library/Application Support/Claude/claude_desktop_config.json'), cursor: path.join(home, 'Library/Application Support/Cursor/User/settings.json'), windsurf: path.join(home, 'Library/Application Support/Windsurf/User/settings.json'), continue: path.join(home, '.continue/config.json'), vscode: path.join(home, 'Library/Application Support/Code/User/settings.json'), zed: path.join(home, '.config/zed/settings.json'), }, linux: { claude: path.join(home, '.config/claude/claude_desktop_config.json'), cursor: path.join(home, '.config/Cursor/User/settings.json'), windsurf: path.join(home, '.config/Windsurf/User/settings.json'), continue: path.join(home, '.continue/config.json'), vscode: path.join(home, '.config/Code/User/settings.json'), zed: path.join(home, '.config/zed/settings.json'), }, win32: { claude: path.join(home, 'AppData/Roaming/Claude/claude_desktop_config.json'), cursor: path.join(home, 'AppData/Roaming/Cursor/User/settings.json'), windsurf: path.join(home, 'AppData/Roaming/Windsurf/User/settings.json'), continue: path.join(home, '.continue/config.json'), vscode: path.join(home, 'AppData/Roaming/Code/User/settings.json'), zed: path.join(home, 'AppData/Roaming/Zed/settings.json'), }, }; return paths[platform] || paths.linux; }; const detectClients = () => { const configPaths = getConfigPaths(); return [ { id: 'claude', name: 'Claude Desktop', emoji: 'πŸ€–', description: 'Anthropic Claude Desktop', configPath: configPaths.claude, detected: fs.existsSync(configPaths.claude), }, { id: 'cursor', name: 'Cursor', emoji: '🎯', description: 'AI-powered code editor', configPath: configPaths.cursor, detected: fs.existsSync(configPaths.cursor), }, { id: 'windsurf', name: 'Windsurf', emoji: 'πŸ„', description: 'Codeium AI IDE', configPath: configPaths.windsurf, detected: fs.existsSync(configPaths.windsurf), }, { id: 'continue', name: 'Continue.dev', emoji: 'πŸ”„', description: 'Open source coding assistant', configPath: configPaths.continue, detected: fs.existsSync(configPaths.continue), }, { id: 'vscode', name: 'VS Code', emoji: 'πŸ’»', description: 'Visual Studio Code', configPath: configPaths.vscode, detected: fs.existsSync(configPaths.vscode), }, { id: 'zed', name: 'Zed', emoji: '⚑', description: 'High-performance editor', configPath: configPaths.zed, detected: fs.existsSync(configPaths.zed), }, ]; }; const ensureConfigDir = (configPath) => { const configDir = path.dirname(configPath); if (!fs.existsSync(configDir)) { fs.mkdirSync(configDir, { recursive: true }); } }; const readConfigSafely = (configPath) => { try { if (fs.existsSync(configPath)) { const content = fs.readFileSync(configPath, 'utf8'); return JSON.parse(content); } } catch (error) { console.warn(`Warning: Could not read config from ${configPath}`); } return {}; }; const smartleadConfig = (apiKey) => ({ command: 'npx', args: ['smartlead-mcp-by-leadmagic'], env: { SMARTLEAD_API_KEY: apiKey, SMARTLEAD_ADVANCED_TOOLS: 'true', SMARTLEAD_ADMIN_TOOLS: 'true', }, }); const installForClient = (client, apiKey) => { try { ensureConfigDir(client.configPath); const config = readConfigSafely(client.configPath); const serverConfig = smartleadConfig(apiKey); switch (client.id) { case 'claude': case 'windsurf': case 'zed': config.mcpServers = { ...config.mcpServers, smartlead: serverConfig }; break; case 'cursor': case 'vscode': config['cline.mcpServers'] = { ...config['cline.mcpServers'], smartlead: serverConfig }; break; case 'continue': { if (!config.mcpServers) config.mcpServers = []; const existingIndex = config.mcpServers.findIndex((s) => s.name === 'smartlead'); const serverWithName = { name: 'smartlead', ...serverConfig }; if (existingIndex >= 0) { config.mcpServers[existingIndex] = serverWithName; } else { config.mcpServers.push(serverWithName); } break; } } fs.writeFileSync(client.configPath, JSON.stringify(config, null, 2)); return { client: client.name, success: true, message: 'Successfully configured', configPath: client.configPath, }; } catch (error) { return { client: client.name, success: false, message: error instanceof Error ? error.message : 'Configuration failed', }; } }; // ===== COMPONENTS ===== const Logo = () => (_jsxs(Box, { flexDirection: "column", alignItems: "center", marginBottom: 2, children: [_jsx(Gradient, { name: "mind", children: _jsx(BigText, { text: "SmartLead", font: "block" }) }), _jsx(Box, { marginTop: -1, children: _jsx(Gradient, { name: "teen", children: _jsx(Text, { bold: true, children: "\uD83D\uDC9C MCP SERVER INSTALLER \uD83D\uDC9C" }) }) }), _jsx(Text, { color: "magenta", dimColor: true, children: "\u2728 by LeadMagic \u2022 Official SmartLead Partner \u2728" })] })); const WelcomeScreen = ({ onNext }) => { const [dots, setDots] = useState(''); useEffect(() => { const interval = setInterval(() => { setDots((prev) => (prev.length >= 3 ? '' : prev + '.')); }, 500); return () => clearInterval(interval); }, []); useInput((input, key) => { if (key.return || input === ' ') { onNext(); } }); return (_jsxs(Box, { flexDirection: "column", padding: 2, borderStyle: "round", borderColor: "magenta", children: [_jsx(Logo, {}), _jsxs(Box, { flexDirection: "column", alignItems: "center", marginBottom: 2, children: [_jsx(Gradient, { name: "passion", children: _jsx(Text, { bold: true, children: "\uD83D\uDE80 The Complete Cold Email Automation Suite \uD83D\uDE80" }) }), _jsxs(Text, { color: "white", children: ["\uD83C\uDFAF", ' ', _jsx(Text, { color: "cyan", bold: true, children: "116+ API Tools" }), ' ', "\u2022 \uD83D\uDEE1\uFE0F", ' ', _jsx(Text, { color: "green", bold: true, children: "Production Ready" }), ' ', "\u2022 \uD83C\uDFA8", ' ', _jsx(Text, { color: "yellow", bold: true, children: "Zero Config" })] }), _jsxs(Text, { color: "white", children: ["\uD83D\uDD27", ' ', _jsx(Text, { color: "magenta", bold: true, children: "TypeScript Native" }), ' ', "\u2022 \uD83C\uDF0D", ' ', _jsx(Text, { color: "cyan", bold: true, children: "Cross Platform" }), ' ', "\u2022 \u26A1", ' ', _jsx(Text, { color: "blue", bold: true, children: "Instant Setup" })] })] }), _jsxs(Box, { flexDirection: "column", alignItems: "center", marginBottom: 2, children: [_jsx(Text, { color: "gray", dimColor: true, children: "\uD83D\uDD17 Compatible with:" }), _jsxs(Text, { color: "white", children: [_jsx(Text, { color: "cyan", children: "Claude" }), " \u2022 ", _jsx(Text, { color: "green", children: "Cursor" }), " \u2022", _jsx(Text, { color: "yellow", children: "Windsurf" }), " \u2022 ", _jsx(Text, { color: "magenta", children: "Continue" }), " \u2022", _jsx(Text, { color: "blue", children: "VS Code" }), " \u2022 ", _jsx(Text, { color: "red", children: "Zed" })] })] }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: "blue", children: [_jsx(Spinner, { type: "dots" }), " Ready to revolutionize your cold email game", dots] }) }), _jsx(Box, { borderStyle: "double", borderColor: "green", padding: 1, children: _jsx(Gradient, { name: "fruit", children: _jsx(Text, { bold: true, children: "\u25B6\uFE0F Press ENTER or SPACE to begin the magic!" }) }) })] })); }; const ApiKeyScreen = ({ onNext, onBack }) => { const [input, setInput] = useState(''); const [error, setError] = useState(''); const [isValidating, setIsValidating] = useState(false); const validateApiKey = async (key) => { setIsValidating(true); setError(''); try { const client = new SmartLeadClient({ apiKey: key }); await client.testConnection(); onNext(key); } catch (err) { if (err instanceof SmartLeadError) { setError(`SmartLead API Error: ${err.message}`); } else { setError('Invalid API key or connection failed'); } } finally { setIsValidating(false); } }; const handleSubmit = () => { if (!input || input.length < 10) { setError('Please enter a valid SmartLead API key (minimum 10 characters)'); } else { validateApiKey(input.trim()); } }; useInput((inputChar, key) => { if (key.escape) { onBack(); } else if (key.return && !isValidating) { handleSubmit(); } }); return (_jsxs(Box, { flexDirection: "column", padding: 2, borderStyle: "round", borderColor: "cyan", children: [_jsx(Logo, {}), _jsx(Box, { borderStyle: "single", borderColor: "red", padding: 1, marginBottom: 1, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Gradient, { name: "morning", children: _jsx(Text, { bold: true, children: "\uD83D\uDD11 Step 1: Enter Your SmartLead API Key (REQUIRED)" }) }), _jsx(Text, { color: "red", children: "\u26A0\uFE0F API key validation is MANDATORY for security!" })] }) }), _jsx(Box, { borderStyle: "single", borderColor: "cyan", padding: 1, marginBottom: 1, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Gradient, { name: "atlas", children: _jsx(Text, { bold: true, children: "\uD83D\uDCCB How to get your API key:" }) }), _jsxs(Text, { children: ["1. Visit: ", _jsx(Link, { url: "https://app.smartlead.ai", children: "https://app.smartlead.ai" })] }), _jsx(Text, { children: "2. Go to Settings \u2192 API Keys" }), _jsx(Text, { children: "3. Generate a new API key" }), _jsx(Text, { children: "4. Copy and paste it below" })] }) }), _jsx(Box, { borderStyle: "single", borderColor: "green", padding: 1, marginBottom: 1, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Gradient, { name: "teen", children: _jsx(Text, { bold: true, children: "Enter your API key:" }) }), _jsx(TextInput, { value: input, onChange: (value) => { setInput(value); if (error) setError(''); }, onSubmit: handleSubmit, placeholder: "Paste your SmartLead API key here...", mask: "\u2022" }), input.length > 0 && input.length < 10 && (_jsx(Text, { color: "yellow", dimColor: true, children: "Need at least 10 characters..." })), input.length >= 10 && _jsx(Text, { color: "green", children: "\u2705 Key format looks good!" })] }) }), error && (_jsx(Box, { borderStyle: "single", borderColor: "red", padding: 1, marginBottom: 1, children: _jsxs(Text, { color: "red", children: ["\u274C ", error] }) })), isValidating && (_jsx(Box, { borderStyle: "single", borderColor: "blue", padding: 1, marginBottom: 1, children: _jsxs(Text, { color: "blue", children: [_jsx(Spinner, { type: "dots" }), " Validating with SmartLead API..."] }) })), _jsx(Box, { borderStyle: "single", borderColor: "gray", padding: 1, children: _jsx(Text, { color: "gray", dimColor: true, children: "Press ENTER to validate \u2022 ESC to go back" }) })] })); }; const ClientSelectionScreen = ({ onNext, onBack }) => { const [clients] = useState(detectClients()); const [selectedClients, setSelectedClients] = useState([]); const items = [ { label: '🌟 All Detected Clients (Recommended)', value: 'all' }, ...clients.map((client) => ({ label: `${client.emoji} ${client.name} ${client.detected ? 'βœ… (detected)' : 'πŸ“± (not found)'}`, value: client.id, })), { label: 'βœ… Continue with selected clients', value: 'continue' }, ]; const handleSelect = (item) => { if (item.value === 'all') { const detectedClients = clients.filter((c) => c.detected); setSelectedClients(detectedClients); } else if (item.value === 'continue') { if (selectedClients.length === 0) { const detectedClients = clients.filter((c) => c.detected); if (detectedClients.length > 0) { onNext(detectedClients); } } else { onNext(selectedClients); } } else { const client = clients.find((c) => c.id === item.value); if (client) { setSelectedClients((prev) => prev.includes(client) ? prev.filter((c) => c.id !== client.id) : [...prev, client]); } } }; useInput((input, key) => { if (key.escape) { onBack(); } }); return (_jsxs(Box, { flexDirection: "column", padding: 2, borderStyle: "round", borderColor: "yellow", children: [_jsx(Logo, {}), _jsx(Box, { borderStyle: "single", borderColor: "yellow", padding: 1, marginBottom: 1, children: _jsx(Gradient, { name: "passion", children: _jsx(Text, { bold: true, children: "\uD83C\uDFAF Step 2: Select Your AI Coding Tools" }) }) }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: "cyan", children: ["Selected: ", selectedClients.map((c) => c.name).join(', ') || 'None (will auto-detect)'] }) }), _jsx(SelectInput, { items: items, onSelect: handleSelect }), _jsx(Box, { borderStyle: "single", borderColor: "gray", padding: 1, marginTop: 1, children: _jsx(Text, { color: "gray", dimColor: true, children: "Use \u2191\u2193 to navigate \u2022 ENTER to select \u2022 ESC to go back" }) })] })); }; const InstallationScreen = ({ apiKey, clients, onComplete, onError }) => { const [currentClient, setCurrentClient] = useState(0); const [results, setResults] = useState([]); useEffect(() => { const install = async () => { const installResults = []; for (let i = 0; i < clients.length; i++) { setCurrentClient(i); const client = clients[i]; try { // Add realistic delay for better UX await new Promise((resolve) => setTimeout(resolve, 1500)); const result = installForClient(client, apiKey); installResults.push(result); setResults([...installResults]); } catch (error) { const errorResult = { client: client.name, success: false, message: error instanceof Error ? error.message : 'Unknown error', }; installResults.push(errorResult); setResults([...installResults]); } } onComplete(installResults); }; install(); }, [apiKey, clients, onComplete]); const progress = Math.round(((currentClient + 1) / clients.length) * 100); return (_jsxs(Box, { flexDirection: "column", padding: 2, borderStyle: "round", borderColor: "green", children: [_jsx(Logo, {}), _jsx(Box, { borderStyle: "single", borderColor: "green", padding: 1, marginBottom: 1, children: _jsx(Gradient, { name: "cristal", children: _jsx(Text, { bold: true, children: "\uD83D\uDD27 Installing SmartLead MCP Server Magic..." }) }) }), _jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: "cyan", children: ["Progress: ", progress, "% complete (", currentClient + 1, "/", clients.length, " clients)"] }), _jsx(Text, { color: "green", children: 'β–ˆ'.repeat(Math.floor(progress / 5)) })] }), clients.map((client, index) => (_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: index < currentClient ? 'green' : index === currentClient ? 'yellow' : 'gray', children: [index < currentClient ? 'βœ…' : index === currentClient ? '⏳' : '⏸️', " ", client.emoji, ' ', client.name] }), index < results.length && (_jsxs(Text, { color: results[index]?.success ? 'green' : 'red', dimColor: true, children: [' ', "- ", results[index]?.message] }))] }, client.id))), currentClient < clients.length && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "blue", children: [_jsx(Spinner, { type: "dots" }), " Configuring ", clients[currentClient]?.name, "..."] }) }))] })); }; const CompletionScreen = ({ results, onExit }) => { const successCount = results.filter((r) => r.success).length; const totalCount = results.length; const [celebration, setCelebration] = useState(0); useEffect(() => { const interval = setInterval(() => { setCelebration((prev) => (prev + 1) % 4); }, 800); return () => clearInterval(interval); }, []); const celebrationEmojis = ['πŸŽ‰', 'πŸš€', '✨', '🎊']; useInput((input, key) => { if (key.return || input === ' ' || key.escape) { onExit(); } }); return (_jsxs(Box, { flexDirection: "column", padding: 2, borderStyle: "round", borderColor: "green", children: [_jsx(Logo, {}), _jsx(Box, { borderStyle: "double", borderColor: "green", padding: 1, marginBottom: 2, children: _jsx(Gradient, { name: "cristal", children: _jsxs(Text, { bold: true, children: [celebrationEmojis[celebration], " Installation Complete! ", celebrationEmojis[celebration]] }) }) }), _jsx(Box, { marginBottom: 2, children: _jsxs(Text, { color: "green", children: ["\u2705 Successfully configured ", successCount, "/", totalCount, " clients"] }) }), results.map((result) => (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: result.success ? 'green' : 'red', children: [result.success ? 'βœ…' : '❌', " ", result.client, ": ", result.message] }) }, result.client))), _jsx(Box, { borderStyle: "single", borderColor: "cyan", padding: 1, marginTop: 2, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Gradient, { name: "teen", children: _jsx(Text, { bold: true, children: "\uD83D\uDE80 Next Steps:" }) }), _jsx(Text, { children: "1. Restart your AI coding tool(s)" }), _jsx(Text, { children: "2. Look for \"smartlead\" in the available tools" }), _jsx(Text, { children: "3. Start automating your cold email campaigns!" }), _jsx(Text, { children: "4. Enjoy 116+ powerful SmartLead tools!" })] }) }), _jsx(Box, { borderStyle: "single", borderColor: "magenta", padding: 1, marginTop: 1, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Gradient, { name: "passion", children: _jsx(Text, { bold: true, children: "\uD83D\uDCDA Resources:" }) }), _jsxs(Text, { children: ["\u2022 GitHub:", ' ', _jsx(Link, { url: "https://github.com/LeadMagic/smartlead-mcp-server", children: "LeadMagic/smartlead-mcp-server" })] }), _jsxs(Text, { children: ["\u2022 SmartLead: ", _jsx(Link, { url: "https://smartlead.ai", children: "smartlead.ai" })] }), _jsxs(Text, { children: ["\u2022 Support: ", _jsx(Link, { url: "mailto:jesse@leadmagic.io", children: "jesse@leadmagic.io" })] })] }) }), _jsx(Box, { borderStyle: "double", borderColor: "magenta", padding: 1, marginTop: 1, children: _jsx(Gradient, { name: "fruit", children: _jsx(Text, { bold: true, children: "Press ENTER, SPACE, or ESC to finish! Thank you! \uD83D\uDC9C" }) }) })] })); }; // ===== MAIN APP ===== const SmartLeadInstaller = () => { const { exit } = useApp(); const [step, setStep] = useState('welcome'); const [apiKey, setApiKey] = useState(''); const [selectedClients, setSelectedClients] = useState([]); const [results, setResults] = useState([]); const [error, setError] = useState(''); const renderStep = () => { switch (step) { case 'welcome': return _jsx(WelcomeScreen, { onNext: () => setStep('apiKey') }); case 'apiKey': return (_jsx(ApiKeyScreen, { onNext: (key) => { setApiKey(key); setStep('clientSelection'); }, onBack: () => setStep('welcome') })); case 'clientSelection': return (_jsx(ClientSelectionScreen, { onNext: (clients) => { setSelectedClients(clients); setStep('installing'); }, onBack: () => setStep('apiKey') })); case 'installing': return (_jsx(InstallationScreen, { apiKey: apiKey, clients: selectedClients, onComplete: (results) => { setResults(results); setStep('complete'); }, onError: (error) => { setError(error); setStep('error'); } })); case 'complete': return _jsx(CompletionScreen, { results: results, onExit: () => exit() }); case 'error': return (_jsxs(Box, { flexDirection: "column", padding: 2, borderStyle: "round", borderColor: "red", children: [_jsxs(Text, { color: "red", children: ["\u274C Installation Error: ", error] }), _jsx(Text, { color: "gray", children: "Press any key to exit..." })] })); default: return _jsx(Text, { children: "Unknown step" }); } }; return renderStep(); }; // ===== ENTRY POINT ===== export { SmartLeadInstaller }; //# sourceMappingURL=installer.js.map