UNPKG

rnr-mcp-server

Version:

A Model Context Protocol (MCP) server for React Native Reusables components, providing AI assistants with access to component source code, demos, and metadata for React Native development.

297 lines (296 loc) 15.6 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. */ import { getFramework } from "./utils/framework.js"; /** * 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 React Native Reusables 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 React Native Reusables based on build tool and package manager", uriTemplate: "resource-template:get_installation_guide?buildTool={buildTool}&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", }; } // Get current framework and determine package name const framework = getFramework(); const packageName = framework === "expo" ? "@react-native-reusables/cli" : "@react-native-reusables/cli"; // Generate installation script based on package manager let installCommand; switch (packageManager.toLowerCase()) { case "npm": installCommand = `npx ${packageName}@latest add ${component}`; break; case "pnpm": installCommand = `pnpm dlx ${packageName}@latest add ${component}`; break; case "yarn": installCommand = `yarn dlx ${packageName}@latest add ${component}`; break; case "bun": installCommand = `bunx --bun ${packageName}@latest add ${component}`; break; default: installCommand = `npx ${packageName}@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 buildTool = extractParam(uri, "buildTool"); const packageManager = extractParam(uri, "packageManager"); // Get current framework first since it's used in validation const currentFramework = getFramework(); if (!buildTool) { return { content: currentFramework === "expo" ? "Missing buildTool parameter. Available options: expo, react-native" : "Missing buildTool parameter. Please specify expo, react-native, etc.", contentType: "text/plain", }; } // Validate build tool for Expo if (currentFramework === "expo" && !["expo", "react-native"].includes(buildTool.toLowerCase())) { return { content: 'Invalid build tool for Expo. Only "expo" and "react-native" are supported.', contentType: "text/plain", }; } if (!packageManager) { return { content: "Missing packageManager parameter. Please specify npm, pnpm, or yarn.", contentType: "text/plain", }; } // Determine package name const packageName = "@react-native-reusables/cli"; // Generate installation guide based on build tool and package manager const guides = { expo: { description: "Installation guide for Expo project", steps: [ "Create an Expo project if you don't have one already:", `${packageManager}${packageManager === "npm" ? " create" : ""} expo my-app`, "", "Navigate to your project directory:", "cd my-app", "", "Install NativeWind (required for React Native Reusables):", packageManager === "npm" ? `npm install nativewind` : packageManager === "pnpm" ? `pnpm add nativewind` : packageManager === "yarn" ? `yarn add nativewind` : packageManager === "bun" ? `bun add nativewind` : `npm install nativewind`, "", "Install React Native Reusables CLI:", packageManager === "npm" ? `npx ${packageName}@latest init` : packageManager === "pnpm" ? `pnpm dlx ${packageName}@latest init` : packageManager === "yarn" ? `yarn dlx ${packageName}@latest init` : packageManager === "bun" ? `bunx --bun ${packageName}@latest init` : `npx ${packageName}@latest init`, "", "Follow the prompts to select your preferences", "", "Once initialized, you can add components:", packageManager === "npm" ? `npx ${packageName}@latest add button` : packageManager === "pnpm" ? `pnpm dlx ${packageName}@latest add button` : packageManager === "yarn" ? `yarn dlx ${packageName}@latest add button` : packageManager === "bun" ? `bunx --bun ${packageName}@latest add button` : `npx ${packageName}@latest add button`, "", "Now you can use the component in your project!", ], }, "react-native": { description: "Installation guide for React Native project", steps: [ "Create a React Native project if you don't have one already:", `${packageManager === "npm" ? "npx" : packageManager === "pnpm" ? "pnpm dlx" : packageManager === "yarn" ? "yarn dlx" : "bunx"} react-native@latest init my-app`, "", "Navigate to your project directory:", "cd my-app", "", "Install NativeWind (required for React Native Reusables):", packageManager === "npm" ? `npm install nativewind` : packageManager === "pnpm" ? `pnpm add nativewind` : packageManager === "yarn" ? `yarn add nativewind` : packageManager === "bun" ? `bun add nativewind` : `npm install nativewind`, "", "Install React Native Reusables CLI:", packageManager === "npm" ? `npx ${packageName}@latest init` : packageManager === "pnpm" ? `pnpm dlx ${packageName}@latest init` : packageManager === "yarn" ? `yarn dlx ${packageName}@latest init` : packageManager === "bun" ? `bunx --bun ${packageName}@latest init` : `npx ${packageName}@latest init`, "", "Follow the prompts to select your preferences", "", "Once initialized, you can add components:", packageManager === "npm" ? `npx ${packageName}@latest add button` : packageManager === "pnpm" ? `pnpm dlx ${packageName}@latest add button` : packageManager === "yarn" ? `yarn dlx ${packageName}@latest add button` : packageManager === "bun" ? `bunx --bun ${packageName}@latest add button` : `npx ${packageName}@latest add button`, "", "Now you can use the component in your project!", ], }, default: { description: "Generic installation guide for React Native", steps: [ "Make sure you have a React Native or Expo project set up", "", "Install NativeWind (required for React Native Reusables):", packageManager === "npm" ? `npm install nativewind` : packageManager === "pnpm" ? `pnpm add nativewind` : packageManager === "yarn" ? `yarn add nativewind` : packageManager === "bun" ? `bun add nativewind` : `npm install nativewind`, "", "Install React Native Reusables CLI:", packageManager === "npm" ? `npx ${packageName}@latest init` : packageManager === "pnpm" ? `pnpm dlx ${packageName}@latest init` : packageManager === "yarn" ? `yarn dlx ${packageName}@latest init` : packageManager === "bun" ? `bunx --bun ${packageName}@latest init` : `npx ${packageName}@latest init`, "", "Follow the prompts to select your preferences", "", "Once initialized, you can add components:", packageManager === "npm" ? `npx ${packageName}@latest add button` : packageManager === "pnpm" ? `pnpm dlx ${packageName}@latest add button` : packageManager === "yarn" ? `yarn dlx ${packageName}@latest add button` : packageManager === "bun" ? `bunx --bun ${packageName}@latest add button` : `npx ${packageName}@latest add button`, "", "Now you can use the component in your project!", ], }, }; // Select appropriate guide based on build tool const guide = guides[buildTool.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; };