UNPKG

@jpisnice/shadcn-ui-mcp-server

Version:

A Model Context Protocol (MCP) server for shadcn/ui components, providing AI assistants with access to component source code, demos, blocks, and metadata.

245 lines (244 loc) 13.2 kB
/** * Resource templates implementation for the Model Context Protocol (MCP) server. * * This file defines resource templates that can be used to dynamically generate * resources based on parameters in the URI. */ /** * Resource template definitions exported to the MCP handler * Each template has a name, description, uriTemplate and contentType */ export const resourceTemplates = [ { name: 'get_install_script_for_component', description: 'Generate installation script for a specific shadcn/ui component based on package manager', uriTemplate: 'resource-template:get_install_script_for_component?packageManager={packageManager}&component={component}', contentType: 'text/plain', }, { name: 'get_installation_guide', description: 'Get the installation guide for shadcn/ui based on framework and package manager', uriTemplate: 'resource-template:get_installation_guide?framework={framework}&packageManager={packageManager}', contentType: 'text/plain', }, ]; // Create a map for easier access in getResourceTemplate const resourceTemplateMap = { 'get_install_script_for_component': resourceTemplates[0], 'get_installation_guide': resourceTemplates[1], }; /** * Extract parameters from URI * @param uri URI to extract from * @param paramName Name of parameter to extract * @returns Parameter value or undefined */ function extractParam(uri, paramName) { const match = uri.match(new RegExp(`${paramName}=([^&]+)`)); return match?.[1]; } /** * Gets a resource template handler for a given URI * @param uri The URI of the resource template * @returns A function that generates the resource */ export const getResourceTemplate = (uri) => { // Component installation script template if (uri.startsWith('resource-template:get_install_script_for_component')) { return async () => { try { const packageManager = extractParam(uri, 'packageManager'); const component = extractParam(uri, 'component'); if (!packageManager) { return { content: 'Missing packageManager parameter. Please specify npm, pnpm, or yarn.', contentType: 'text/plain' }; } if (!component) { return { content: 'Missing component parameter. Please specify the component name.', contentType: 'text/plain' }; } // Generate installation script based on package manager let installCommand; switch (packageManager.toLowerCase()) { case 'npm': installCommand = `npx shadcn@latest add ${component}`; break; case 'pnpm': installCommand = `pnpm dlx shadcn@latest add ${component}`; break; case 'yarn': installCommand = `yarn dlx shadcn@latest add ${component}`; break; case 'bun': installCommand = `bunx --bun shadcn@latest add ${component}`; break; default: installCommand = `npx shadcn@latest add ${component}`; } return { content: installCommand, contentType: 'text/plain', }; } catch (error) { return { content: `Error generating installation script: ${error instanceof Error ? error.message : String(error)}`, contentType: 'text/plain', }; } }; } // Installation guide template if (uri.startsWith('resource-template:get_installation_guide')) { return async () => { try { const framework = extractParam(uri, 'framework'); const packageManager = extractParam(uri, 'packageManager'); if (!framework) { return { content: 'Missing framework parameter. Please specify next, vite, remix, etc.', contentType: 'text/plain' }; } if (!packageManager) { return { content: 'Missing packageManager parameter. Please specify npm, pnpm, or yarn.', contentType: 'text/plain' }; } // Generate installation guide based on framework and package manager const guides = { next: { description: "Installation guide for Next.js project", steps: [ "Create a Next.js project if you don't have one already:", `${packageManager} create next-app my-app`, "", "Navigate to your project directory:", "cd my-app", "", "Add shadcn/ui to your project:", packageManager === 'npm' ? 'npx shadcn-ui@latest init' : packageManager === 'pnpm' ? 'pnpm dlx shadcn-ui@latest init' : packageManager === 'yarn' ? 'yarn dlx shadcn-ui@latest init' : packageManager === 'bun' ? 'bunx --bun shadcn-ui@latest init' : 'npx shadcn-ui@latest init', "", "Follow the prompts to select your preferences", "", "Once initialized, you can add components:", packageManager === 'npm' ? 'npx shadcn-ui@latest add button' : packageManager === 'pnpm' ? 'pnpm dlx shadcn-ui@latest add button' : packageManager === 'yarn' ? 'yarn dlx shadcn-ui@latest add button' : packageManager === 'bun' ? 'bunx --bun shadcn-ui@latest add button' : 'npx shadcn-ui@latest add button', "", "Now you can use the component in your project!" ] }, vite: { description: "Installation guide for Vite project", steps: [ "Create a Vite project if you don't have one already:", `${packageManager}${packageManager === 'npm' ? ' create' : ''} vite my-app -- --template react-ts`, "", "Navigate to your project directory:", "cd my-app", "", "Install dependencies:", `${packageManager} ${packageManager === 'npm' ? 'install' : 'add'} -D tailwindcss postcss autoprefixer`, "", "Initialize Tailwind CSS:", "npx tailwindcss init -p", "", "Add shadcn/ui to your project:", packageManager === 'npm' ? 'npx shadcn-ui@latest init' : packageManager === 'pnpm' ? 'pnpm dlx shadcn-ui@latest init' : packageManager === 'yarn' ? 'yarn dlx shadcn-ui@latest init' : packageManager === 'bun' ? 'bunx --bun shadcn-ui@latest init' : 'npx shadcn-ui@latest init', "", "Follow the prompts to select your preferences", "", "Once initialized, you can add components:", packageManager === 'npm' ? 'npx shadcn-ui@latest add button' : packageManager === 'pnpm' ? 'pnpm dlx shadcn-ui@latest add button' : packageManager === 'yarn' ? 'yarn dlx shadcn-ui@latest add button' : packageManager === 'bun' ? 'bunx --bun shadcn-ui@latest add button' : 'npx shadcn-ui@latest add button', "", "Now you can use the component in your project!" ] }, remix: { description: "Installation guide for Remix project", steps: [ "Create a Remix project if you don't have one already:", `${packageManager === 'npm' ? 'npx' : packageManager === 'pnpm' ? 'pnpm dlx' : packageManager === 'yarn' ? 'yarn dlx' : 'bunx'} create-remix my-app`, "", "Navigate to your project directory:", "cd my-app", "", "Install dependencies:", `${packageManager} ${packageManager === 'npm' ? 'install' : 'add'} -D tailwindcss postcss autoprefixer`, "", "Initialize Tailwind CSS:", "npx tailwindcss init -p", "", "Add shadcn/ui to your project:", packageManager === 'npm' ? 'npx shadcn-ui@latest init' : packageManager === 'pnpm' ? 'pnpm dlx shadcn-ui@latest init' : packageManager === 'yarn' ? 'yarn dlx shadcn-ui@latest init' : packageManager === 'bun' ? 'bunx --bun shadcn-ui@latest init' : 'npx shadcn-ui@latest init', "", "Follow the prompts to select your preferences", "", "Once initialized, you can add components:", packageManager === 'npm' ? 'npx shadcn-ui@latest add button' : packageManager === 'pnpm' ? 'pnpm dlx shadcn-ui@latest add button' : packageManager === 'yarn' ? 'yarn dlx shadcn-ui@latest add button' : packageManager === 'bun' ? 'bunx --bun shadcn-ui@latest add button' : 'npx shadcn-ui@latest add button', "", "Now you can use the component in your project!" ] }, default: { description: "Generic installation guide", steps: [ "Make sure you have a React project set up", "", "Add shadcn/ui to your project:", packageManager === 'npm' ? 'npx shadcn-ui@latest init' : packageManager === 'pnpm' ? 'pnpm dlx shadcn-ui@latest init' : packageManager === 'yarn' ? 'yarn dlx shadcn-ui@latest init' : packageManager === 'bun' ? 'bunx --bun shadcn-ui@latest init' : 'npx shadcn-ui@latest init', "", "Follow the prompts to select your preferences", "", "Once initialized, you can add components:", packageManager === 'npm' ? 'npx shadcn-ui@latest add button' : packageManager === 'pnpm' ? 'pnpm dlx shadcn-ui@latest add button' : packageManager === 'yarn' ? 'yarn dlx shadcn-ui@latest add button' : packageManager === 'bun' ? 'bunx --bun shadcn-ui@latest add button' : 'npx shadcn-ui@latest add button', "", "Now you can use the component in your project!" ] } }; // Select appropriate guide based on framework const guide = guides[framework.toLowerCase()] || guides.default; return { content: `# ${guide.description} with ${packageManager}\n\n${guide.steps.join('\n')}`, contentType: 'text/plain', }; } catch (error) { return { content: `Error generating installation guide: ${error instanceof Error ? error.message : String(error)}`, contentType: 'text/plain', }; } }; } return undefined; };