Skip to main content
Glama
GetComponentVisualTool.ts4.97 kB
/** * GetComponentVisualTool * * DESIGN PATTERNS: * - Tool pattern with getDefinition() and execute() methods * - Service delegation for business logic * - JSON Schema validation for inputs * * CODING STANDARDS: * - Implement Tool interface from ../types * - Use TOOL_NAME constant with snake_case (e.g., 'get_component_visual') * - Return CallToolResult with content array * - Handle errors with isError flag * - Delegate complex logic to services * * AVOID: * - Complex business logic in execute method * - Unhandled promise rejections * - Missing input validation */ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; import { GetUiComponentService } from '../services'; import type { GetUiComponentInput, GetUiComponentResult } from '../services'; import type { Tool, ToolDefinition } from '../types'; /** * Template for visual review instructions returned with component screenshots. * Guides the LLM to verify visual correctness of the rendered component. * @param imagePath - Path to the component screenshot image * @returns Formatted markdown string with visual review instructions */ const REVIEW_INSTRUCTIONS_TEMPLATE = (imagePath: string): string => ` ## Visual Review Instructions Please review the component screenshot and story code to verify visual correctness: 1. **Read the screenshot** at: ${imagePath} 2. **Compare with the story code** to ensure the rendered output matches expectations 3. **Check for visual issues**: - Are all variants rendering correctly? - Are colors, spacing, and typography as expected? - Are interactive states (hover, disabled, loading) properly styled? - Is the layout and alignment correct? If you notice any visual discrepancies between the code and the rendered output, please report them. `; export class GetComponentVisualTool implements Tool<GetUiComponentInput> { static readonly TOOL_NAME = 'get_component_visual'; private service: GetUiComponentService; /** * Creates a new GetComponentVisualTool instance. * @param service - Optional service instance for dependency injection (useful for testing) */ constructor(service?: GetUiComponentService) { this.service = service ?? new GetUiComponentService(); } /** * Returns the tool definition including name, description, and input schema. * @returns Tool definition with JSON Schema for input validation */ getDefinition(): ToolDefinition { return { name: GetComponentVisualTool.TOOL_NAME, description: 'Get a image preview of a UI component with app-specific design system configuration. Useful when work on the frontend design to review the UI quickly without running the full app.', inputSchema: { type: 'object', properties: { componentName: { type: 'string', minLength: 1, description: 'The name of the component to capture (e.g., "Button", "Card", etc.)', }, appPath: { type: 'string', minLength: 1, description: 'The app path (relative or absolute) to load design system configuration from (e.g., "apps/agiflow-app"). The design system config is read from {appPath}/project.json', }, storyName: { type: 'string', minLength: 1, description: 'The story name to render (e.g., "Playground", "Default"). Defaults to "Playground".', }, darkMode: { type: 'boolean', description: 'Whether to render the component in dark mode. Defaults to true.', }, selector: { type: 'string', minLength: 1, description: 'CSS selector to target specific element for screenshot. When provided, screenshot will auto-resize to element dimensions. Defaults to "#root".', }, }, required: ['componentName', 'appPath'], additionalProperties: false, }, }; } /** * Executes the tool to get a UI component preview. * @param input - The input parameters for getting the component * @returns Promise resolving to CallToolResult with component info or error */ async execute(input: GetUiComponentInput): Promise<CallToolResult> { try { const result: GetUiComponentResult = await this.service.getComponent(input); const reviewInstructions = REVIEW_INSTRUCTIONS_TEMPLATE(result.imagePath); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, { type: 'text', text: reviewInstructions, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown 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/AgiFlow/aicode-toolkit'

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