Skip to main content
Glama
components.ts8.98 kB
import fs from "node:fs"; import path from "node:path"; import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; // TypeScript interfaces for BigBlocks registry interface BigBlocksComponent { name: string; type: string; description: string; files?: string[]; dependencies?: string[]; registryDependencies?: string[]; } interface BigBlocksRegistry { components: BigBlocksComponent[]; version?: string; } interface OrganizedComponents { [category: string]: { [subcategory: string]: BigBlocksComponent[]; }; } // Load BigBlocks registry data function loadBigBlocksRegistry(): BigBlocksRegistry | null { try { const registryPath = path.resolve( "node_modules/bigblocks/registry/registry.json", ); const registryData = JSON.parse(fs.readFileSync(registryPath, "utf-8")); return registryData as BigBlocksRegistry; } catch (error) { console.error("Failed to load BigBlocks registry:", error); return null; } } // Organize components by type for easier browsing function organizeComponentsByType( registry: BigBlocksRegistry, ): OrganizedComponents { const organized: OrganizedComponents = {}; if (!registry?.components) return organized; for (const component of registry.components) { const [category, subcategory] = component.type.split(":"); if (!organized[category]) { organized[category] = {}; } if (!organized[category][subcategory]) { organized[category][subcategory] = []; } organized[category][subcategory].push(component); } return organized; } const componentSearchSchema = z.object({ category: z .string() .optional() .describe("Component category to search in (component, hook)"), type: z .string() .optional() .describe( "Component type to filter by (auth, social, wallet, market, profile, backup, ui, bap, provider, layout)", ), component: z .string() .optional() .describe("Specific component name to get details for"), search: z .string() .optional() .describe("Search term to find components by name or description"), showAll: z.boolean().optional().describe("Show all available components"), }); /** * Register the BigBlocks component discovery tool */ export function registerBigBlocksComponentTool(server: McpServer): void { server.tool( "bigblocks_components", "Discover and learn about BigBlocks React components from the official registry. BigBlocks provides 96+ production-ready components for Bitcoin applications.\n\n" + "Usage examples:\n" + '- List all components: {"showAll": true}\n' + '- Browse by category: {"category": "component"}\n' + '- Filter by type: {"type": "social"}\n' + '- Get component details: {"component": "auth-flow"}\n' + '- Search components: {"search": "authentication"}\n\n' + "Categories:\n" + "- component: React components (auth, social, wallet, market, profile, backup, ui, bap, provider, layout)\n" + "- hook: React hooks for various functionalities\n\n" + "Types:\n" + "- auth: Authentication and login components\n" + "- social: Social media and networking\n" + "- wallet: Bitcoin wallet operations\n" + "- market: NFT and token marketplace\n" + "- profile: User profile management\n" + "- backup: Key backup and recovery\n" + "- ui: General UI components\n" + "- bap: Bitcoin Application Protocol\n" + "- provider: Context providers\n" + "- layout: Layout components", { args: componentSearchSchema }, async ({ args }) => { try { const registry = loadBigBlocksRegistry(); if (!registry) { return { content: [ { type: "text", text: "Error: Could not load BigBlocks registry data", }, ], isError: true, }; } const { category, type, component, search, showAll } = args; const organized = organizeComponentsByType(registry); // Show specific component details if (component) { const comp = registry.components.find((c) => c.name === component); if (!comp) { const available = registry.components.map((c) => c.name).join(", "); return { content: [ { type: "text", text: `Component "${component}" not found. Available components: ${available}`, }, ], isError: true, }; } let result = `# ${comp.name}\n\n`; result += `**Type:** ${comp.type}\n`; result += `**Description:** ${comp.description}\n\n`; if (comp.files?.length) { result += `**Files:**\n${comp.files.map((f) => `- ${f}`).join("\n")}\n\n`; } if (comp.dependencies?.length) { result += `**Dependencies:** ${comp.dependencies.join(", ")}\n\n`; } if (comp.registryDependencies?.length) { result += `**Registry Dependencies:** ${comp.registryDependencies.join(", ")}\n\n`; } // Determine the actual component/hook name from files const mainFile = comp.files?.[0]; if (mainFile) { const fileName = path.basename(mainFile, path.extname(mainFile)); result += `**Import:**\n\`\`\`tsx\nimport { ${fileName} } from 'bigblocks';\n\`\`\`\n\n`; } return { content: [{ type: "text", text: result }] }; } // Search components if (search) { const searchTerm = search.toLowerCase(); const matchingComponents = registry.components.filter( (comp) => comp.name.toLowerCase().includes(searchTerm) || comp.description.toLowerCase().includes(searchTerm) || comp.type.toLowerCase().includes(searchTerm), ); let result = `# BigBlocks Components Search: "${search}"\n\n`; if (matchingComponents.length === 0) { result += "No components found matching your search."; } else { result += `Found ${matchingComponents.length} component(s):\n\n`; for (const comp of matchingComponents) { result += `## ${comp.name} (${comp.type})\n`; result += `${comp.description}\n\n`; } } return { content: [{ type: "text", text: result }] }; } // Filter by category and/or type if (category || type) { let filtered = registry.components; if (category) { filtered = filtered.filter((comp) => comp.type.startsWith(`${category}:`), ); } if (type) { filtered = filtered.filter((comp) => comp.type.includes(`:${type}`), ); } let result = `# BigBlocks Components${category ? ` - ${category}` : ""}${type ? ` - ${type}` : ""}\n\n`; if (filtered.length === 0) { result += "No components found matching your criteria."; } else { result += `Found ${filtered.length} component(s):\n\n`; for (const comp of filtered) { result += `## ${comp.name}\n**Type:** ${comp.type}\n**Description:** ${comp.description}\n\n`; } } return { content: [{ type: "text", text: result }] }; } // Show all components organized if (showAll) { let result = "# BigBlocks Component Registry\n\n"; result += `**Version:** ${registry.version}\n`; result += `**Total Components:** ${registry.components.length}\n\n`; for (const [cat, subcats] of Object.entries(organized)) { result += `## ${cat.charAt(0).toUpperCase() + cat.slice(1)}s\n\n`; for (const [subcat, components] of Object.entries(subcats)) { result += `### ${subcat.charAt(0).toUpperCase() + subcat.slice(1)} (${components.length})\n`; for (const comp of components) { result += `- **${comp.name}**: ${comp.description}\n`; } result += "\n"; } } result += '\n**Get details:** Use {"component": "component-name"} for specific information\n'; result += '**Filter:** Use {"category": "component", "type": "social"} to filter by type'; return { content: [{ type: "text", text: result }] }; } // Default: show overview const componentCount = Object.values(organized.component || {}).reduce( (sum, comps) => sum + comps.length, 0, ); const hookCount = Object.values(organized.hook || {}).reduce( (sum, hooks) => sum + hooks.length, 0, ); return { content: [ { type: "text", text: `# BigBlocks Component Registry **Version:** ${registry.version} **Total:** ${registry.components.length} items **Categories:** - **Components:** ${componentCount} React components - **Hooks:** ${hookCount} React hooks **Component Types:** ${Object.keys(organized.component || {}) .map( (type) => `- **${type}**: ${organized.component[type].length} components`, ) .join("\n")} Use {"showAll": true} to see all components, {"category": "component"} to browse components, or {"component": "name"} for details.`, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }, ); }

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/b-open-io/bsv-mcp'

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