UNPKG

@templation/mcp-server

Version:

Enhanced MCP server for Templation - Advanced GitHub repository search, AI-powered template conversion, and comprehensive template management directly in Cursor

756 lines β€’ 43.8 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js'; import fetch from 'node-fetch'; import dotenv from 'dotenv'; dotenv.config(); // Configuration with fallbacks const API_BASE_URL = process.env.TEMPLATION_API_URL || 'https://templation-api.up.railway.app'; const API_KEY = process.env.TEMPLATION_API_KEY; if (!API_KEY) { console.error('❌ TEMPLATION_API_KEY environment variable is required'); console.error('πŸ“‹ Get your API key at: https://templation.up.railway.app/api-keys'); process.exit(1); } // Simple in-memory cache for performance const cache = new Map(); const server = new Server({ name: 'templation', version: '2.0.0', }, { capabilities: { tools: {}, }, }); // Enhanced cache helper function getCached(key) { const cached = cache.get(key); if (cached && Date.now() - cached.timestamp < cached.ttl) { return cached.data; } cache.delete(key); return null; } function setCache(key, data, ttlMs = 300000) { cache.set(key, { data, timestamp: Date.now(), ttl: ttlMs }); } // Enhanced API call helper with retry logic and better error handling async function apiCall(endpoint, options = {}, retries = 3) { const url = `${API_BASE_URL}${endpoint}`; for (let attempt = 1; attempt <= retries; attempt++) { try { const response = await fetch(url, { timeout: 30000, // 30 second timeout ...options, headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${API_KEY}`, 'User-Agent': 'Templation-MCP-Server/2.0.0', ...options.headers, }, }); if (!response.ok) { const errorText = await response.text(); // Handle specific error cases if (response.status === 401) { throw new Error(`Authentication failed. Please check your API key at https://templation.up.railway.app/api-keys`); } else if (response.status === 403) { throw new Error(`Access forbidden. Your API key may not have sufficient permissions.`); } else if (response.status === 429) { if (attempt < retries) { // Wait before retry on rate limit await new Promise(resolve => setTimeout(resolve, 1000 * attempt)); continue; } throw new Error(`Rate limit exceeded. Please try again in a few minutes.`); } else if (response.status >= 500) { if (attempt < retries) { // Retry on server errors await new Promise(resolve => setTimeout(resolve, 1000 * attempt)); continue; } throw new Error(`Server error (${response.status}). Please try again later.`); } throw new Error(`API call failed (${response.status}): ${errorText}`); } const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { return await response.json(); } else { return await response.text(); } } catch (error) { if (attempt === retries) { if (error instanceof Error) { throw error; } throw new Error(`API call failed: ${String(error)}`); } // Wait before retry await new Promise(resolve => setTimeout(resolve, 1000 * attempt)); } } } // Utility functions for better response formatting function formatTemplateResult(template, index) { const tags = Array.isArray(template.tags) ? template.tags.join(', ') : Array.isArray(template.tech_stack) ? template.tech_stack.join(', ') : 'None'; const createdDate = template.created_at ? new Date(template.created_at).toLocaleDateString() : 'Unknown'; const lastUsed = template.last_used ? new Date(template.last_used).toLocaleDateString() : 'Never'; return `${index + 1}. **${template.name}**\n` + ` πŸ“ ${template.description || 'No description'}\n` + ` πŸ”— Source: ${template.source_repo_name || template.source_repo_url || 'Unknown'}\n` + ` 🏷️ Tags: ${tags}\n` + ` πŸ“Š Usage: ${template.usage_count || 0} times\n` + ` πŸ“… Created: ${createdDate}${template.last_used ? ` | Last used: ${lastUsed}` : ''}\n` + ` ${template.is_favorite ? '⭐ Favorite' : ''}`; } function formatRepoResult(repo, index) { const stars = repo.metrics?.stars || 0; const forks = repo.metrics?.forks || 0; const techStack = Array.isArray(repo.tech_stack) ? repo.tech_stack.slice(0, 5).join(', ') : 'N/A'; const difficulty = repo.customization_difficulty || 'medium'; const difficultyEmoji = { easy: '🟒', medium: '🟑', hard: 'πŸ”΄' }[difficulty] || '🟑'; return `${index + 1}. **${repo.name}** ⭐ ${stars.toLocaleString()} 🍴 ${forks.toLocaleString()}\n` + ` πŸ“ ${repo.visual_summary || repo.description || 'No description available'}\n` + ` πŸ”— ${repo.url}\n` + ` πŸ› οΈ Tech: ${techStack}\n` + ` ${difficultyEmoji} Difficulty: ${difficulty}\n` + ` ${repo.demo_url ? `🌐 Demo: ${repo.demo_url}\n` : ''}` + ` ${repo.screenshot_url ? `πŸ“Έ Preview available\n` : ''}`; } // List available tools with enhanced descriptions server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'search_templates', description: 'Search your saved templates by name, description, or technology. Find templates you\'ve created or converted from GitHub repositories.', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search query - can include project names, technologies, or keywords (e.g., "React portfolio", "FastAPI", "e-commerce")', }, limit: { type: 'number', description: 'Maximum number of results to return (1-50, default: 10)', minimum: 1, maximum: 50, default: 10, }, }, required: ['query'], }, }, { name: 'search_exemplar', description: 'Discover high-quality GitHub repositories for inspiration. Search by project type, technology, or features to find repositories you can use as templates.', inputSchema: { type: 'object', properties: { description: { type: 'string', description: 'Describe what you want to build. Be specific for better results (e.g., "React e-commerce with Stripe payments", "Python FastAPI with authentication", "Vue.js dashboard with charts")', }, filters: { type: 'object', description: 'Optional filters to refine your search results', properties: { language: { type: 'string', description: 'Programming language filter (e.g., "TypeScript", "Python", "JavaScript", "Go", "Rust")', }, min_stars: { type: 'number', description: 'Minimum number of GitHub stars (helps find popular, well-maintained repositories)', minimum: 0, }, max_age_days: { type: 'number', description: 'Maximum age in days - only show repositories updated within this timeframe (e.g., 365 for last year)', minimum: 1, }, }, }, }, required: ['description'], }, }, { name: 'template_converter', description: 'Convert any GitHub repository into a personalized, step-by-step template with detailed setup instructions and customization guidance.', inputSchema: { type: 'object', properties: { repo_url: { type: 'string', description: 'Full GitHub repository URL (e.g., "https://github.com/vercel/next.js", "https://github.com/fastapi/fastapi")', pattern: '^https://github\\.com/[^/]+/[^/]+/?$', }, template_description: { type: 'string', description: 'Describe how you want to customize this template and what you\'ll use it for (e.g., "Portfolio website for a data scientist", "E-commerce site for handmade jewelry", "API for a food delivery app")', }, user_context: { type: 'object', description: 'Additional context to personalize the template conversion', properties: { project_name: { type: 'string', description: 'Your specific project name (e.g., "AcmeCorp Website", "MyFoodApp API")', }, preferred_style: { type: 'string', description: 'Design/coding style preference (e.g., "modern", "minimal", "corporate", "playful")', }, additional_features: { type: 'array', items: { type: 'string' }, description: 'Additional features you want to include (e.g., ["dark mode", "authentication", "payment integration", "analytics"])', }, target_audience: { type: 'string', description: 'Who will use this (e.g., "developers", "small businesses", "students")', }, deployment_preference: { type: 'string', description: 'Preferred deployment platform (e.g., "Vercel", "Netlify", "Railway", "AWS", "self-hosted")', }, }, }, }, required: ['repo_url', 'template_description'], }, }, { name: 'get_user_info', description: 'Get detailed information about your Templation account, including GitHub connection status and account statistics.', inputSchema: { type: 'object', properties: { include_stats: { type: 'boolean', description: 'Include additional statistics like template count and recent activity', default: true, }, }, }, }, { name: 'get_dashboard_stats', description: 'Get comprehensive dashboard statistics including template count, repository analysis, recent activity, and usage metrics.', inputSchema: { type: 'object', properties: { include_recent_activity: { type: 'boolean', description: 'Include list of recent templates and activity', default: false, }, }, }, }, { name: 'get_template_details', description: 'Get detailed information about a specific template, including setup instructions, customization points, and usage history.', inputSchema: { type: 'object', properties: { template_id: { type: 'string', description: 'The unique ID of the template (from search results or dashboard)', }, include_setup_guide: { type: 'boolean', description: 'Include detailed setup and customization instructions', default: true, }, }, required: ['template_id'], }, }, ], }; }); // Handle tool calls with enhanced functionality server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case 'search_templates': { const { query, limit = 10 } = args; // Validate inputs if (!query.trim()) { return { content: [ { type: 'text', text: `❌ Please provide a search query.\n\nπŸ’‘ **Examples:**\nβ€’ "React portfolio"\nβ€’ "FastAPI authentication"\nβ€’ "e-commerce"\nβ€’ "dashboard"`, }, ], }; } const clampedLimit = Math.max(1, Math.min(50, limit)); const cacheKey = `search_templates:${query}:${clampedLimit}`; try { // Check cache first let templates = getCached(cacheKey); if (!templates) { templates = await apiCall(`/api/search/templates?q=${encodeURIComponent(query)}&limit=${clampedLimit}`); setCache(cacheKey, templates, 180000); // 3 minute cache } if (!templates || templates.length === 0) { return { content: [ { type: 'text', text: `πŸ” No templates found for "${query}"\n\nπŸ’‘ **Try:**\nβ€’ Different keywords (e.g., "React" instead of "ReactJS")\nβ€’ Broader terms (e.g., "web app" instead of "specific framework")\nβ€’ Technology names (e.g., "Python", "TypeScript", "Vue")\n\n🌐 **Create your first template:**\n1. Use \`search_exemplar\` to find a good repository\n2. Use \`template_converter\` to convert it\n3. Or visit https://templation.up.railway.app/templates`, }, ], }; } const formattedResults = templates.map((template, index) => formatTemplateResult(template, index)).join('\n\n'); const totalText = templates.length === clampedLimit ? `${templates.length}+ templates` : `${templates.length} template${templates.length === 1 ? '' : 's'}`; return { content: [ { type: 'text', text: `🎯 Found ${totalText} for "${query}":\n\n${formattedResults}\n\nπŸ’‘ **Next steps:**\nβ€’ Use \`get_template_details\` with a template ID for setup instructions\nβ€’ Visit https://templation.up.railway.app/templates to manage templates\nβ€’ Use \`template_converter\` to create new templates from GitHub repos`, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `❌ Error searching templates: ${error instanceof Error ? error.message : 'Unknown error'}\n\nπŸ”§ **Troubleshooting:**\nβ€’ Check your API key at https://templation.up.railway.app/api-keys\nβ€’ Ensure you have created some templates first\nβ€’ Try a simpler search query\nβ€’ Check your internet connection`, }, ], }; } } case 'search_exemplar': { const { description, filters } = args; // Validate inputs if (!description.trim()) { return { content: [ { type: 'text', text: `❌ Please provide a description of what you want to build.\n\nπŸ’‘ **Good examples:**\nβ€’ "React e-commerce website with Stripe payments"\nβ€’ "Python FastAPI with JWT authentication"\nβ€’ "Vue.js dashboard with real-time charts"\nβ€’ "Next.js blog with dark mode"\nβ€’ "Express.js REST API with MongoDB"`, }, ], }; } const cacheKey = `search_exemplar:${description}:${JSON.stringify(filters || {})}`; try { // Check cache first let searchResult = getCached(cacheKey); if (!searchResult) { searchResult = await apiCall('/api/search-exemplar', { method: 'POST', body: JSON.stringify({ description, filters: filters || {}, }), }); setCache(cacheKey, searchResult, 600000); // 10 minute cache for repo searches } if (!searchResult.repos || searchResult.repos.length === 0) { const filterText = filters ? Object.entries(filters) .filter(([_, value]) => value !== undefined && value !== null) .map(([key, value]) => `${key}: ${value}`) .join(', ') : ''; return { content: [ { type: 'text', text: `πŸ” No repositories found for "${description}"${filterText ? ` with filters (${filterText})` : ''}\n\nπŸ’‘ **Try:**\nβ€’ Broader search terms (e.g., "React app" instead of "React e-commerce with Stripe and dark mode")\nβ€’ Different keywords (e.g., "web scraper" instead of "data extraction tool")\nβ€’ Remove or relax filters\nβ€’ Popular tech combinations (e.g., "MERN stack", "JAMstack", "MEAN stack")\n\n🌟 **Popular searches:**\nβ€’ "React portfolio website"\nβ€’ "Python web scraper"\nβ€’ "Node.js REST API"\nβ€’ "Vue dashboard"\nβ€’ "Flutter mobile app"`, }, ], }; } const formattedResults = searchResult.repos.map((repo, index) => formatRepoResult(repo, index)).join('\n\n'); const searchTime = searchResult.search_time_ms ? ` (${searchResult.search_time_ms}ms)` : ''; const filterSummary = filters ? Object.entries(filters) .filter(([_, value]) => value !== undefined && value !== null) .map(([key, value]) => { if (key === 'min_stars') return `⭐ ${value}+ stars`; if (key === 'max_age_days') return `πŸ“… Updated within ${value} days`; if (key === 'language') return `πŸ’» ${value}`; return `${key}: ${value}`; }).join(' β€’ ') : ''; return { content: [ { type: 'text', text: `🎯 Found ${searchResult.repos.length} repositories for "${description}"${searchTime}\n${filterSummary ? `πŸ” Filters: ${filterSummary}\n` : ''}\n${formattedResults}\n\nπŸ’‘ **Next steps:**\nβ€’ Copy a repository URL and use \`template_converter\` to create your personalized template\nβ€’ Visit the repository to explore the code and documentation\nβ€’ Check demo links to see the project in action\nβ€’ Look for repositories with good documentation and recent activity`, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `❌ Error searching repositories: ${error instanceof Error ? error.message : 'Unknown error'}\n\nπŸ”§ **This might be due to:**\nβ€’ GitHub API rate limits (try again in a few minutes)\nβ€’ Network connectivity issues\nβ€’ Invalid search parameters\nβ€’ Temporary service unavailability\n\nπŸ’‘ **Try:**\nβ€’ Simpler search terms\nβ€’ Removing filters temporarily\nβ€’ Waiting a few minutes and trying again`, }, ], }; } } case 'template_converter': { const { repo_url, template_description, user_context } = args; // Enhanced validation if (!repo_url.trim()) { return { content: [ { type: 'text', text: `❌ Please provide a GitHub repository URL.\n\nπŸ’‘ **Format:** https://github.com/owner/repository\n**Examples:**\nβ€’ https://github.com/vercel/next.js\nβ€’ https://github.com/fastapi/fastapi\nβ€’ https://github.com/vuejs/vue`, }, ], }; } if (!template_description.trim()) { return { content: [ { type: 'text', text: `❌ Please provide a description of how you want to customize this template.\n\nπŸ’‘ **Good examples:**\nβ€’ "Portfolio website for a data scientist with project showcases"\nβ€’ "E-commerce site for handmade jewelry with payment integration"\nβ€’ "Task management app for small teams with real-time collaboration"\nβ€’ "Blog platform for tech writers with syntax highlighting"`, }, ], }; } // Validate GitHub URL format const githubUrlPattern = /^https:\/\/github\.com\/[^\/]+\/[^\/]+\/?$/; if (!githubUrlPattern.test(repo_url.trim())) { return { content: [ { type: 'text', text: `❌ Invalid GitHub URL format.\n\nβœ… **Correct format:** https://github.com/owner/repository\n❌ **Your input:** ${repo_url}\n\nπŸ’‘ **Make sure to:**\nβ€’ Include the full URL starting with https://github.com/\nβ€’ Use the main repository URL (not a specific file or branch)\nβ€’ Ensure the repository is publicly accessible`, }, ], }; } try { const startTime = Date.now(); const conversionResult = await apiCall('/api/template-converter', { method: 'POST', body: JSON.stringify({ repo_url: repo_url.trim(), template_description: template_description.trim(), user_context: user_context || {}, }), }); const conversionTime = Date.now() - startTime; // Format the response with enhanced structure let result = `# πŸŽ‰ Template Conversion Complete!\n\n`; result += `**πŸ“¦ Repository:** ${repo_url}\n`; result += `**🎯 Template Purpose:** ${template_description}\n`; result += `**⏱️ Conversion Time:** ${conversionTime}ms\n\n`; if (user_context?.project_name) { result += `**🏷️ Project Name:** ${user_context.project_name}\n`; } if (user_context?.preferred_style) { result += `**🎨 Style Preference:** ${user_context.preferred_style}\n`; } if (user_context?.target_audience) { result += `**πŸ‘₯ Target Audience:** ${user_context.target_audience}\n`; } if (user_context?.deployment_preference) { result += `**πŸš€ Deployment:** ${user_context.deployment_preference}\n`; } result += `\n`; if (conversionResult.conversion_steps?.length > 0) { result += `## πŸ“‹ Step-by-Step Conversion Guide\n`; conversionResult.conversion_steps.forEach((step, index) => { result += `${index + 1}. ${step}\n`; }); result += `\n`; } if (conversionResult.setup_commands?.length > 0) { result += `## πŸš€ Setup Commands\n\`\`\`bash\n`; conversionResult.setup_commands.forEach((command) => { result += `${command}\n`; }); result += `\`\`\`\n\n`; } if (conversionResult.files_to_modify?.length > 0) { result += `## πŸ“ Files to Customize\n`; conversionResult.files_to_modify.forEach((file) => { result += `β€’ \`${file}\`\n`; }); result += `\n`; } if (conversionResult.customization_points?.length > 0) { result += `## 🎨 Key Customization Areas\n`; conversionResult.customization_points.forEach((point) => { result += `β€’ ${point}\n`; }); result += `\n`; } if (user_context?.additional_features?.length && user_context.additional_features.length > 0) { result += `## ✨ Additional Features to Implement\n`; user_context.additional_features.forEach((feature) => { result += `β€’ ${feature}\n`; }); result += `\n`; } if (conversionResult.expected_outcome) { result += `## 🎯 Expected Outcome\n${conversionResult.expected_outcome}\n\n`; } if (conversionResult.template_id) { result += `## πŸ’Ύ Template Saved Successfully!\n`; result += `**Template ID:** \`${conversionResult.template_id}\`\n\n`; result += `🌐 **Access your template:**\n`; result += `β€’ Web Dashboard: https://templation.up.railway.app/templates/${conversionResult.template_id}\n`; result += `β€’ All Templates: https://templation.up.railway.app/templates\n\n`; result += `πŸ” **Find it later:** Use \`search_templates\` with keywords from your description\n`; result += `πŸ“‹ **Get details:** Use \`get_template_details\` with template ID \`${conversionResult.template_id}\``; } return { content: [ { type: 'text', text: result, }, ], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; return { content: [ { type: 'text', text: `❌ Template conversion failed: ${errorMessage}\n\nπŸ”§ **Common issues:**\nβ€’ **Invalid URL:** Make sure the GitHub repository URL is correct and publicly accessible\nβ€’ **Private repository:** The repository must be public or you need access\nβ€’ **Repository not found:** Check if the repository exists and hasn't been renamed\nβ€’ **Rate limits:** GitHub API limits may be exceeded, try again in a few minutes\nβ€’ **Large repository:** Very large repositories may take longer to process\n\nπŸ’‘ **Tips:**\nβ€’ Use popular, well-maintained repositories for better results\nβ€’ Ensure the repository has a clear structure and documentation\nβ€’ Try repositories with fewer than 10,000 files for faster processing\n\n🌐 **Get help:** Visit https://templation.up.railway.app/account for support`, }, ], }; } } case 'get_user_info': { const { include_stats = true } = args; try { const userInfo = await apiCall('/api/users/me'); let stats = null; if (include_stats) { try { stats = await apiCall('/api/users/dashboard/stats'); } catch (e) { // Stats are optional, continue without them } } let result = `πŸ‘€ **User Account Information**\n\n`; result += `**Name:** ${userInfo.name || 'Not provided'}\n`; result += `**Email:** ${userInfo.email || 'Not provided'}\n`; result += `**GitHub:** ${userInfo.github_username ? `@${userInfo.github_username} βœ…` : '❌ Not connected'}\n`; result += `**Account Created:** ${userInfo.created_at ? new Date(userInfo.created_at).toLocaleDateString() : 'Unknown'}\n`; if (!userInfo.github_connected) { result += `\nπŸ”— **Connect GitHub:** Visit https://templation.up.railway.app/account to connect your GitHub account for better template analysis\n`; } if (stats) { result += `\nπŸ“Š **Account Statistics:**\n`; result += `β€’ Templates: ${stats.total_templates || 0}\n`; result += `β€’ Repositories Analyzed: ${stats.repositories_analyzed || 0}\n`; result += `β€’ Favorites: ${stats.favorites || 0}\n`; result += `β€’ Recent Activity: ${stats.recent_activity || 0} templates this week\n`; result += `β€’ API Keys: ${stats.active_api_keys || 0} active\n`; } result += `\n🌐 **Quick Links:**\n`; result += `β€’ Dashboard: https://templation.up.railway.app/dashboard\n`; result += `β€’ Templates: https://templation.up.railway.app/templates\n`; result += `β€’ Account Settings: https://templation.up.railway.app/account\n`; result += `β€’ API Keys: https://templation.up.railway.app/api-keys`; return { content: [ { type: 'text', text: result, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `❌ Error getting user info: ${error instanceof Error ? error.message : 'Unknown error'}\n\nπŸ”§ **Troubleshooting:**\nβ€’ Check your API key at https://templation.up.railway.app/api-keys\nβ€’ Ensure your API key has the correct permissions\nβ€’ Try refreshing your API key if it's old\n\nπŸ’‘ **Need help?** Visit https://templation.up.railway.app/account`, }, ], }; } } case 'get_dashboard_stats': { const { include_recent_activity = false } = args; try { const stats = await apiCall('/api/users/dashboard/stats'); let result = `πŸ“Š **Dashboard Statistics**\n\n`; result += `**πŸ“ Total Templates:** ${stats.total_templates || 0}\n`; result += `**πŸ” Repositories Analyzed:** ${stats.repositories_analyzed || 0}\n`; result += `**⭐ Favorite Templates:** ${stats.favorites || 0}\n`; result += `**πŸ“ˆ Recent Activity:** ${stats.recent_activity || 0} templates this week\n`; result += `**πŸ”‘ Active API Keys:** ${stats.active_api_keys || 0}\n`; if (stats.most_used_technologies?.length > 0) { result += `**πŸ› οΈ Top Technologies:** ${stats.most_used_technologies.slice(0, 5).join(', ')}\n`; } if (stats.total_templates === 0) { result += `\nπŸ’‘ **Get started:**\n`; result += `1. Use \`search_exemplar\` to find interesting repositories\n`; result += `2. Use \`template_converter\` to create your first template\n`; result += `3. Visit https://templation.up.railway.app/templates to manage templates\n`; } else { result += `\n🎯 **Quick actions:**\n`; result += `β€’ Use \`search_templates\` to find your templates\n`; result += `β€’ Use \`template_converter\` to create more templates\n`; result += `β€’ Visit https://templation.up.railway.app/dashboard for detailed analytics\n`; } if (include_recent_activity && stats.recent_templates?.length > 0) { result += `\nπŸ“‹ **Recent Templates:**\n`; stats.recent_templates.slice(0, 5).forEach((template, index) => { result += `${index + 1}. ${template.name} (${new Date(template.created_at).toLocaleDateString()})\n`; }); } result += `\n🌐 **View full dashboard:** https://templation.up.railway.app/dashboard`; return { content: [ { type: 'text', text: result, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `❌ Error getting dashboard stats: ${error instanceof Error ? error.message : 'Unknown error'}\n\nπŸ”§ **This might be due to:**\nβ€’ API key authentication issues\nβ€’ Temporary service unavailability\nβ€’ Network connectivity problems\n\nπŸ’‘ **Try:**\nβ€’ Checking your API key at https://templation.up.railway.app/api-keys\nβ€’ Waiting a moment and trying again\nβ€’ Visiting the web dashboard at https://templation.up.railway.app/dashboard`, }, ], }; } } case 'get_template_details': { const { template_id, include_setup_guide = true } = args; if (!template_id?.trim()) { return { content: [ { type: 'text', text: `❌ Please provide a template ID.\n\nπŸ’‘ **Get template IDs from:**\nβ€’ \`search_templates\` results\nβ€’ Template conversion results\nβ€’ Web dashboard at https://templation.up.railway.app/templates`, }, ], }; } try { const template = await apiCall(`/api/templates/${template_id}`); let result = `πŸ“‹ **Template Details**\n\n`; result += `**Name:** ${template.name}\n`; result += `**Description:** ${template.description || 'No description'}\n`; result += `**Source Repository:** ${template.source_repo_url}\n`; result += `**Created:** ${template.created_at ? new Date(template.created_at).toLocaleDateString() : 'Unknown'}\n`; result += `**Usage Count:** ${template.usage_count || 0} times\n`; result += `**Last Used:** ${template.last_used ? new Date(template.last_used).toLocaleDateString() : 'Never'}\n`; result += `**Favorite:** ${template.is_favorite ? '⭐ Yes' : '❌ No'}\n`; if (template.tech_stack?.length > 0) { result += `**Technologies:** ${template.tech_stack.join(', ')}\n`; } if (include_setup_guide && template.template_data) { const data = template.template_data; if (data.conversion_steps?.length > 0) { result += `\n## πŸ“‹ Setup Instructions\n`; data.conversion_steps.forEach((step, index) => { result += `${index + 1}. ${step}\n`; }); } if (data.setup_commands?.length > 0) { result += `\n## πŸš€ Setup Commands\n\`\`\`bash\n`; data.setup_commands.forEach((command) => { result += `${command}\n`; }); result += `\`\`\`\n`; } if (data.files_to_modify?.length > 0) { result += `\n## πŸ“ Files to Customize\n`; data.files_to_modify.forEach((file) => { result += `β€’ \`${file}\`\n`; }); } if (data.customization_points?.length > 0) { result += `\n## 🎨 Customization Points\n`; data.customization_points.forEach((point) => { result += `β€’ ${point}\n`; }); } if (data.expected_outcome) { result += `\n## 🎯 Expected Outcome\n${data.expected_outcome}\n`; } } result += `\n🌐 **Web View:** https://templation.up.railway.app/templates/${template_id}\n`; result += `πŸ”— **Source Code:** ${template.source_repo_url}`; return { content: [ { type: 'text', text: result, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `❌ Error getting template details: ${error instanceof Error ? error.message : 'Unknown error'}\n\nπŸ”§ **Possible issues:**\nβ€’ Template ID not found or invalid\nβ€’ Template may have been deleted\nβ€’ API key doesn't have access to this template\nβ€’ Temporary service issue\n\nπŸ’‘ **Try:**\nβ€’ Using \`search_templates\` to find the correct template ID\nβ€’ Checking the template exists at https://templation.up.railway.app/templates\nβ€’ Verifying your API key permissions`, }, ], }; } } default: throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}. Available tools: search_templates, search_exemplar, template_converter, get_user_info, get_dashboard_stats, get_template_details`); } } catch (error) { if (error instanceof McpError) { throw error; } // Enhanced error logging for debugging console.error(`Tool execution failed for ${name}:`, error); throw new McpError(ErrorCode.InternalError, `Tool execution failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } }); async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('πŸš€ Templation MCP Server v2.0.0 running on stdio'); console.error('πŸ“‹ Get your API key: https://templation.up.railway.app/api-keys'); console.error('🌐 Web Dashboard: https://templation.up.railway.app/dashboard'); } main().catch((error) => { console.error('πŸ’₯ Fatal error in main():', error); process.exit(1); }); //# sourceMappingURL=index-backup.js.map