Skip to main content
Glama

component-builder

Generate UI component code snippets from documentation for integration into Vue.js projects using shadcn-vue library.

Instructions

Retrieve documentation for all filtered components and charts to prepare for component generation, This tool ONLY returns the text snippet for that UI component. After calling this tool, you must edit or add files to integrate the snippet into the codebase.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
iconNoicon module of the componentlucide
componentsYescomponents from components-filter tool
chartsYescharts from components-filter tool

Implementation Reference

  • The execute handler for the 'component-builder' tool. It filters components and charts by necessity, fetches their documentation concurrently using Context7 API via ComponentServices, structures the docs into markdown, and returns a text prompt for generating the component code.
    execute: async (params) => { try { const necessityFilter = services.ComponentServices.createNecessityFilter("optional"); // 并发处理所有组件文档 const componentPromises = params.components .filter(necessityFilter) .map(async (component) => { const processedDoc = await services.ComponentServices.fetchLibraryDocumentation( "/unovue/shadcn-vue", { topic: component.name, tokens: 700, } ); return { name: component.name, type: "component", doc: JSON.stringify(processedDoc), }; }); // 并发处理所有图表文档 const chartPromises = params.charts.filter(necessityFilter).map(async (chart) => { const processedDoc = await services.ComponentServices.fetchLibraryDocumentation( "/unovue/shadcn-vue", { topic: chart.name, tokens: 700, } ); return { name: chart.name, type: "chart", doc: JSON.stringify(processedDoc), }; }); // 等待所有文档处理完成 const [componentResults, chartResults] = await Promise.all([ Promise.all(componentPromises), Promise.all(chartPromises), ]); const filteredComponents = { components: componentResults, charts: chartResults, }; // 转为结构化 markdown 内容 const structuredMarkdown = services.ComponentServices.convertToStructuredMarkdown(filteredComponents); const prompt = `${getComponentPrompt(params.icon, structuredMarkdown)}`; return { content: [ { type: "text", text: prompt, }, ], }; } catch (error) { console.error("Error executing component-builder tool:", error); throw error; } },
  • Input schema for the 'component-builder' tool defining icon preference, list of components, and list of charts from prior filtering step.
    parameters: z.object({ icon: z .enum(["@nuxt/icon", "lucide"]) .describe("icon module of the component") .optional() .default("lucide"), components: z .array(services.ComponentSchema) .describe("components from components-filter tool"), charts: z.array(services.ComponentSchema).describe("charts from components-filter tool"), }),
  • Registration of the 'component-builder' tool on the FastMCP server, including name, description, parameters schema, and execute handler reference.
    // component-builder tool 读取所有组件文档 server.addTool({ name: "component-builder", description: "Retrieve documentation for all filtered components and charts to prepare for component generation, This tool ONLY returns the text snippet for that UI component. After calling this tool, you must edit or add files to integrate the snippet into the codebase.", parameters: z.object({ icon: z .enum(["@nuxt/icon", "lucide"]) .describe("icon module of the component") .optional() .default("lucide"), components: z .array(services.ComponentSchema) .describe("components from components-filter tool"), charts: z.array(services.ComponentSchema).describe("charts from components-filter tool"), }), execute: async (params) => { try { const necessityFilter = services.ComponentServices.createNecessityFilter("optional"); // 并发处理所有组件文档 const componentPromises = params.components .filter(necessityFilter) .map(async (component) => { const processedDoc = await services.ComponentServices.fetchLibraryDocumentation( "/unovue/shadcn-vue", { topic: component.name, tokens: 700, } ); return { name: component.name, type: "component", doc: JSON.stringify(processedDoc), }; }); // 并发处理所有图表文档 const chartPromises = params.charts.filter(necessityFilter).map(async (chart) => { const processedDoc = await services.ComponentServices.fetchLibraryDocumentation( "/unovue/shadcn-vue", { topic: chart.name, tokens: 700, } ); return { name: chart.name, type: "chart", doc: JSON.stringify(processedDoc), }; }); // 等待所有文档处理完成 const [componentResults, chartResults] = await Promise.all([ Promise.all(componentPromises), Promise.all(chartPromises), ]); const filteredComponents = { components: componentResults, charts: chartResults, }; // 转为结构化 markdown 内容 const structuredMarkdown = services.ComponentServices.convertToStructuredMarkdown(filteredComponents); const prompt = `${getComponentPrompt(params.icon, structuredMarkdown)}`; return { content: [ { type: "text", text: prompt, }, ], }; } catch (error) { console.error("Error executing component-builder tool:", error); throw error; } }, });
  • Base Zod schema for a single component or chart item, used in arrays for 'component-builder' input parameters. Defines name, necessity level, and justification.
    export const ComponentSchema = z.object({ name: z.string(), necessity: z.enum(["critical", "important", "optional"]), justification: z.string(), });
  • Helper method called by the handler to convert fetched component/chart documentation into a structured Markdown format for the generation prompt.
    static convertToStructuredMarkdown(filteredComponents: { components: Array<{ name: string; type: string; doc: string }>; charts: Array<{ name: string; type: string; doc: string }>; }): string { let markdown = "# Shadcn-Vue Components Documentation\n\n"; // 处理组件部分 if (filteredComponents.components.length > 0) { markdown += "## 📦 Components\n\n"; filteredComponents.components.forEach((component, index) => { markdown += `### ${index + 1}. ${ component.name.charAt(0).toUpperCase() + component.name.slice(1) } Component\n\n`; try { // 尝试解析 JSON 文档 const docData = JSON.parse(component.doc); if (typeof docData === "string") { // 如果是字符串,直接使用 markdown += `${docData}\n\n`; } else if (docData && typeof docData === "object") { // 如果是对象,格式化显示 if (docData.content) { markdown += `${docData.content}\n\n`; } else { markdown += `\`\`\`json\n${JSON.stringify(docData, null, 2)}\n\`\`\`\n\n`; } } } catch { // 如果解析失败,直接使用原始文档 markdown += `${component.doc}\n\n`; } markdown += "---\n\n"; }); } // 处理图表部分 if (filteredComponents.charts.length > 0) { markdown += "## 📊 Charts\n\n"; filteredComponents.charts.forEach((chart, index) => { markdown += `### ${index + 1}. ${ chart.name.charAt(0).toUpperCase() + chart.name.slice(1) } Chart\n\n`; try { // 尝试解析 JSON 文档 const docData = JSON.parse(chart.doc); if (typeof docData === "string") { // 如果是字符串,直接使用 markdown += `${docData}\n\n`; } else if (docData && typeof docData === "object") { // 如果是对象,格式化显示 if (docData.content) { markdown += `${docData.content}\n\n`; } else { markdown += `\`\`\`json\n${JSON.stringify(docData, null, 2)}\n\`\`\`\n\n`; } } } catch { // 如果解析失败,直接使用原始文档 markdown += `${chart.doc}\n\n`; } markdown += "---\n\n"; }); } // 添加总结信息 markdown += "## 📋 Summary\n\n"; markdown += `- **Total Components**: ${filteredComponents.components.length}\n`; markdown += `- **Total Charts**: ${filteredComponents.charts.length}\n`; markdown += `- **Total Items**: ${ filteredComponents.components.length + filteredComponents.charts.length }\n\n`; return markdown; }

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/HelloGGX/shadcn-vue-mcp'

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