Skip to main content
Glama

documcp

by tosin2013
recommend-ssg.ts10.6 kB
import { z } from 'zod'; import { MCPToolResponse, formatMCPResponse } from '../types/api.js'; import { initializeMemory } from '../memory/index.js'; // SSG scoring matrix based on ADR-003 export interface SSGRecommendation { recommended: 'jekyll' | 'hugo' | 'docusaurus' | 'mkdocs' | 'eleventy'; confidence: number; reasoning: string[]; alternatives: Array<{ name: string; score: number; pros: string[]; cons: string[]; }>; } const inputSchema = z.object({ analysisId: z.string(), preferences: z .object({ priority: z.enum(['simplicity', 'features', 'performance']).optional(), ecosystem: z.enum(['javascript', 'python', 'ruby', 'go', 'any']).optional(), }) .optional(), }); export async function recommendSSG(args: unknown): Promise<{ content: any[] }> { const startTime = Date.now(); const { analysisId, preferences } = inputSchema.parse(args); const prioritizeSimplicity = preferences?.priority === 'simplicity'; const ecosystemPreference = preferences?.ecosystem; try { // Try to retrieve analysis from memory let analysisData = null; try { const manager = await initializeMemory(); const analysis = await manager.recall(analysisId); if (analysis && analysis.data) { // Handle the wrapped content structure if (analysis.data.content && Array.isArray(analysis.data.content)) { // Extract the JSON from the first text content const firstContent = analysis.data.content[0]; if (firstContent && firstContent.type === 'text' && firstContent.text) { try { analysisData = JSON.parse(firstContent.text); } catch (parseError) { // If parse fails, try the direct data analysisData = analysis.data; } } } else { // Direct data structure analysisData = analysis.data; } } } catch (error) { // If memory retrieval fails, continue with fallback logic console.warn(`Could not retrieve analysis ${analysisId} from memory:`, error); } // Determine recommendation based on analysis data if available let finalRecommendation: 'jekyll' | 'hugo' | 'docusaurus' | 'mkdocs' | 'eleventy'; let reasoning: string[] = []; let confidence = 0.85; if (analysisData) { // Use actual analysis data to make informed recommendation const ecosystem = analysisData.dependencies?.ecosystem || 'unknown'; const hasReact = analysisData.dependencies?.packages?.some( (p: string) => p.includes('react') || p.includes('next'), ); const complexity = analysisData.documentation?.estimatedComplexity || 'moderate'; const teamSize = analysisData.recommendations?.teamSize || 'small'; // Logic based on real analysis if (ecosystem === 'python') { finalRecommendation = 'mkdocs'; reasoning = [ 'Python ecosystem detected - MkDocs integrates naturally', 'Simple configuration with YAML', 'Material theme provides excellent UI out of the box', 'Strong Python community support', ]; } else if (ecosystem === 'ruby') { finalRecommendation = 'jekyll'; reasoning = [ 'Ruby ecosystem detected - Jekyll is the native choice', 'GitHub Pages native support', 'Simple static site generation', 'Extensive theme ecosystem', ]; } else if (hasReact || ecosystem === 'javascript') { if (complexity === 'complex' || teamSize === 'large') { finalRecommendation = 'docusaurus'; reasoning = [ 'JavaScript/TypeScript ecosystem with React detected', 'Complex project structure benefits from Docusaurus features', 'Built-in versioning and internationalization', 'MDX support for interactive documentation', ]; } else if (prioritizeSimplicity) { finalRecommendation = 'eleventy'; reasoning = [ 'JavaScript ecosystem with simplicity priority', 'Minimal configuration required', 'Fast build times', 'Flexible templating options', ]; } else { finalRecommendation = 'docusaurus'; reasoning = [ 'JavaScript/TypeScript ecosystem detected', 'Modern React-based framework', 'Active community and regular updates', 'Great developer experience', ]; } } else if (ecosystem === 'go') { finalRecommendation = 'hugo'; reasoning = [ 'Go ecosystem detected - Hugo is written in Go', 'Extremely fast build times', 'No runtime dependencies', 'Excellent for large documentation sites', ]; } else { // Default logic when ecosystem is unknown if (prioritizeSimplicity) { finalRecommendation = 'jekyll'; reasoning = [ 'Simple setup and configuration', 'GitHub Pages native support', 'Extensive documentation and community', 'Mature and stable platform', ]; } else { finalRecommendation = 'docusaurus'; reasoning = [ 'Modern documentation framework', 'Rich feature set out of the box', 'Great for technical documentation', 'Active development and support', ]; } } // Apply preference overrides if (ecosystemPreference && ecosystemPreference !== 'any') { if (ecosystemPreference === 'python') { finalRecommendation = 'mkdocs'; reasoning.unshift('Python ecosystem explicitly requested'); } else if (ecosystemPreference === 'ruby') { finalRecommendation = 'jekyll'; reasoning.unshift('Ruby ecosystem explicitly requested'); } else if (ecosystemPreference === 'go') { finalRecommendation = 'hugo'; reasoning.unshift('Go ecosystem explicitly requested'); } else if (ecosystemPreference === 'javascript') { if (finalRecommendation !== 'docusaurus' && finalRecommendation !== 'eleventy') { finalRecommendation = prioritizeSimplicity ? 'eleventy' : 'docusaurus'; reasoning.unshift('JavaScript ecosystem explicitly requested'); } } } // Adjust confidence based on data quality if (analysisData.structure?.totalFiles > 100) { confidence = Math.min(0.95, confidence + 0.05); } if (analysisData.documentation?.hasReadme && analysisData.documentation?.hasDocs) { confidence = Math.min(0.95, confidence + 0.05); } } else { // Fallback logic when no analysis data is available const baseRecommendation = prioritizeSimplicity ? 'jekyll' : 'docusaurus'; finalRecommendation = ecosystemPreference === 'python' ? 'mkdocs' : baseRecommendation; reasoning = [ 'Recommendation based on preferences without full analysis', 'Consider running analyze_repository for more accurate recommendation', ]; confidence = 0.65; // Lower confidence without analysis data } const recommendation: SSGRecommendation = { recommended: finalRecommendation, confidence, reasoning, alternatives: getAlternatives(finalRecommendation, prioritizeSimplicity), }; const response: MCPToolResponse<SSGRecommendation> = { success: true, data: recommendation, metadata: { toolVersion: '1.0.0', executionTime: Date.now() - startTime, timestamp: new Date().toISOString(), analysisId, }, recommendations: [ { type: 'info', title: 'SSG Recommendation', description: `${recommendation.recommended} recommended with ${( recommendation.confidence * 100 ).toFixed(0)}% confidence`, }, ], nextSteps: [ { action: 'Generate Configuration', toolRequired: 'generate_config', description: `Create ${recommendation.recommended} configuration files`, priority: 'high', }, ], }; return formatMCPResponse(response); } catch (error) { const errorResponse: MCPToolResponse = { success: false, error: { code: 'RECOMMENDATION_FAILED', message: `Failed to generate SSG recommendation: ${error}`, resolution: 'Ensure analysis ID is valid and preferences are correctly formatted', }, metadata: { toolVersion: '1.0.0', executionTime: Date.now() - startTime, timestamp: new Date().toISOString(), analysisId, }, }; return formatMCPResponse(errorResponse); } } function getAlternatives( recommended: string, prioritizeSimplicity: boolean, ): SSGRecommendation['alternatives'] { const allSSGs = [ { name: 'Jekyll', score: prioritizeSimplicity ? 0.85 : 0.7, pros: ['Simple setup', 'GitHub Pages native', 'Extensive themes', 'Ruby ecosystem'], cons: ['Ruby dependency', 'Slower builds for large sites', 'Limited dynamic features'], }, { name: 'Hugo', score: prioritizeSimplicity ? 0.65 : 0.75, pros: ['Extremely fast builds', 'No dependencies', 'Go templating', 'Great for large sites'], cons: ['Steeper learning curve', 'Go templating may be unfamiliar', 'Less flexible themes'], }, { name: 'Docusaurus', score: prioritizeSimplicity ? 0.7 : 0.9, pros: ['React-based', 'Rich features', 'MDX support', 'Built-in versioning'], cons: ['More complex setup', 'Node.js dependency', 'Heavier than static generators'], }, { name: 'MkDocs', score: prioritizeSimplicity ? 0.8 : 0.75, pros: ['Simple setup', 'Python-based', 'Great themes', 'Easy configuration'], cons: ['Python dependency', 'Less flexible than React-based', 'Limited customization'], }, { name: 'Eleventy', score: prioritizeSimplicity ? 0.75 : 0.7, pros: ['Minimal config', 'Fast builds', 'Flexible templates', 'JavaScript ecosystem'], cons: [ 'Less opinionated', 'Fewer built-in features', 'Requires more setup for complex sites', ], }, ]; // Filter out the recommended SSG and sort by score return allSSGs .filter((ssg) => ssg.name.toLowerCase() !== recommended.toLowerCase()) .sort((a, b) => b.score - a.score) .slice(0, 2); // Return top 2 alternatives }

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/tosin2013/documcp'

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