Skip to main content
Glama
mednabouli

MCP Multi-Context Hook Generator

by mednabouli
enrichComponents.ts4.11 kB
// mcp/generator/enrichComponents.ts import { ComponentInfo } from '../crawler/components'; import { mcpAgentConfig } from '../config/mcp-ai.config'; export interface AIProp { name: string; description: string; defaultValue?: string; } export interface AIComponentResponse { props: AIProp[]; usage: string; } // -------------------- // Helper: build prompt // -------------------- function buildComponentPrompt(comp: ComponentInfo) { return ` You are a senior React/TypeScript expert. Analyze this component and enrich its props with: 1. Short description (what it represents) 2. Realistic default values 3. Usage snippet Component: - Name: ${comp.name} - File: ${comp.filePath} - Props: ${comp.props.map((p) => ` - ${p.name}: ${p.type}${p.optional ? ' (optional)' : ''}`).join('\n')} Reply in JSON ONLY with: { "props": [ { "name": "...", "description": "...", "defaultValue": "..." } ], "usage": "tsx code example" } `; } // -------------------- // Helper: retry wrapper // -------------------- async function tryWithRetries<T>(fn: () => Promise<T>, maxRetries = 2): Promise<T | null> { let lastError: any; for (let i = 0; i <= maxRetries; i++) { try { return await fn(); } catch (err) { lastError = err; console.warn(`⚠️ AI call failed, retry ${i + 1}/${maxRetries}...`); } } console.error('❌ All AI retries failed:', lastError); return null; } // -------------------- // Mock AI backends // -------------------- async function callOpenAI(comp: ComponentInfo, prompt: string): Promise<AIComponentResponse> { // Placeholder for actual OpenAI API call return { props: comp.props.map((p) => ({ name: p.name, description: `OpenAI description for ${p.name}`, defaultValue: p.defaultValue, })), usage: `OpenAI usage snippet for ${comp.name}`, }; } async function callCopilot(comp: ComponentInfo, prompt: string): Promise<AIComponentResponse> { return { props: comp.props.map((p) => ({ name: p.name, description: `Copilot description for ${p.name}`, defaultValue: p.defaultValue, })), usage: `Copilot usage snippet for ${comp.name}`, }; } async function callCustomAI(comp: ComponentInfo, prompt: string): Promise<AIComponentResponse> { return { props: comp.props.map((p) => ({ name: p.name, description: `Custom AI description for ${p.name}`, defaultValue: p.defaultValue, })), usage: `Custom AI usage snippet for ${comp.name}`, }; } // -------------------- // Main function // -------------------- export async function enrichComponents( components: ComponentInfo[], aiAgent?: 'none' | 'copilot' | 'openai' | 'custom', ): Promise<ComponentInfo[]> { const enriched: ComponentInfo[] = []; aiAgent = aiAgent || mcpAgentConfig.defaultAgent; for (const comp of components) { const prompt = buildComponentPrompt(comp); // Skip AI enrichment if (aiAgent === 'none' || !mcpAgentConfig.enableAI) { enriched.push(comp); continue; } // Dynamic AI selection let aiResponse: AIComponentResponse | null = null; switch (aiAgent) { case 'openai': aiResponse = await tryWithRetries( () => callOpenAI(comp, prompt), mcpAgentConfig.maxRetries, ); break; case 'copilot': aiResponse = await tryWithRetries( () => callCopilot(comp, prompt), mcpAgentConfig.maxRetries, ); break; case 'custom': aiResponse = await tryWithRetries( () => callCustomAI(comp, prompt), mcpAgentConfig.maxRetries, ); break; } // Merge AI data into ComponentInfo if (aiResponse) { comp.props = comp.props.map((p) => { const found = aiResponse!.props.find((ai) => ai.name === p.name); return { ...p, description: found?.description ?? '', defaultValue: found?.defaultValue ?? '', }; }); (comp as any).usage = aiResponse.usage ?? ''; } enriched.push(comp); } return enriched; }

Latest Blog Posts

MCP directory API

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

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mednabouli/MCPV2'

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