Skip to main content
Glama

similarity-figma

Compare Figma design prototypes with generated code page screenshots to verify visual consistency and ensure accurate implementation.

Instructions

获取Figma原型图,请你结合项目源码并通过原型图与生成的代码页面的截图进行相似性比对

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
fileKeyYesThe key of the Figma file to fetch, often found in a provided URL like figma.com/(file|design)/<fileKey>/...
nodeIdNoThe ID of the node to fetch, often found as URL parameter node-id=<nodeId>, always use if provided
urlYes当前项目代码页面的URL地址,注意不是figma网址

Implementation Reference

  • The execute function that implements the core logic of the 'similarity-figma' tool: fetches Figma image using fileKey/nodeId, screenshots the project URL, converts to image content using imageContent, and bundles with a prompt for similarity analysis.
    execute: async ({
      url,
      fileKey,
      nodeId,
    }, {
      session,
    }: {
      session: any
    }) => {
      try {
        const figmaService = this.figmaToolsCore.figmaService
        const screenshotService = new ScreenshotService()
    
        console.log(`Processing similarity check for URL: ${url}, Figma fileKey: ${fileKey}, nodeId: ${nodeId || 'not provided'}`)
    
        // 分步执行并添加错误处理
        let figmaImg
        try {
          figmaImg = await figmaService.getImageData(fileKey, nodeId as string)
          console.log('Successfully fetched Figma image')
        } catch (figmaError) {
          Logger.error('Failed to fetch Figma image:', figmaError)
          return {
            isError: true,
            content: [{ type: 'text', text: `Error fetching Figma image: ${figmaError instanceof Error ? figmaError.message : JSON.stringify(figmaError)}` }],
          }
        }
    
        let screenshotImg
        try {
          screenshotImg = await screenshotService.takeScreenshot(url)
          console.log('Successfully captured screenshot')
        } catch (screenshotError) {
          Logger.error('Failed to take screenshot:', screenshotError)
          return {
            isError: true,
            content: [{ type: 'text', text: `Error taking screenshot of ${url}: ${screenshotError instanceof Error ? screenshotError.message : JSON.stringify(screenshotError)}` }],
          }
        }
    
        // 处理图片转换,添加错误处理
        let figmaImgData
        let screenshotImgData
    
        try {
          figmaImgData = await imageContent({
            url: figmaImg,
          })
          console.log('Successfully converted Figma image')
        } catch (figmaConvertError) {
          Logger.error('Failed to convert Figma image:', figmaConvertError)
          return {
            isError: true,
            content: [{ type: 'text', text: `Error converting Figma image: ${figmaConvertError instanceof Error ? figmaConvertError.message : JSON.stringify(figmaConvertError)}` }],
          }
        }
    
        try {
          screenshotImgData = await imageContent({
            buffer: screenshotImg,
          })
          console.log('Successfully converted screenshot image')
        } catch (screenshotConvertError) {
          Logger.error('Failed to convert screenshot image:', screenshotConvertError)
          return {
            isError: true,
            content: [{ type: 'text', text: `Error converting screenshot image: ${screenshotConvertError instanceof Error ? screenshotConvertError.message : JSON.stringify(screenshotConvertError)}` }],
          }
        }
    
        // console.log('figmaImgData', figmaImgData)
        console.log('screenshotImgData', screenshotImgData)
    
        const prompt = similarityPrompt
    
        return {
          content: [
            { type: 'text', text: prompt },
            figmaImgData,
            screenshotImgData,
          ],
        }
      } catch (error) {
        const message = error instanceof Error ? error.message : JSON.stringify(error)
        Logger.error(`Error fetching file ${fileKey}:`, message)
        return {
          isError: true,
          content: [{ type: 'text', text: `Error fetching file: ${message}` }],
        }
      }
    },
  • Zod schema defining the input parameters for the tool: url (project page URL), fileKey (Figma file key), nodeId (optional node ID).
    parameters: z.object({
      url: z
        .string()
        .describe('当前项目代码页面的URL地址,注意不是figma网址'),
      fileKey: z
        .string()
        .describe(
          'The key of the Figma file to fetch, often found in a provided URL like figma.com/(file|design)/<fileKey>/...',
        ),
      nodeId: z
        .string()
        .optional()
        .describe(
          'The ID of the node to fetch, often found as URL parameter node-id=<nodeId>, always use if provided',
        ),
    }),
  • Registers the 'similarity-figma' tool using server.addTool(), including name, description, parameters schema, and execute handler.
    this.server.addTool({
      name: 'similarity-figma',
      description: '获取Figma原型图,请你结合项目源码并通过原型图与生成的代码页面的截图进行相似性比对',
      parameters: z.object({
        url: z
          .string()
          .describe('当前项目代码页面的URL地址,注意不是figma网址'),
        fileKey: z
          .string()
          .describe(
            'The key of the Figma file to fetch, often found in a provided URL like figma.com/(file|design)/<fileKey>/...',
          ),
        nodeId: z
          .string()
          .optional()
          .describe(
            'The ID of the node to fetch, often found as URL parameter node-id=<nodeId>, always use if provided',
          ),
      }),
      execute: async ({
        url,
        fileKey,
        nodeId,
      }, {
        session,
      }: {
        session: any
      }) => {
        try {
          const figmaService = this.figmaToolsCore.figmaService
          const screenshotService = new ScreenshotService()
    
          console.log(`Processing similarity check for URL: ${url}, Figma fileKey: ${fileKey}, nodeId: ${nodeId || 'not provided'}`)
    
          // 分步执行并添加错误处理
          let figmaImg
          try {
            figmaImg = await figmaService.getImageData(fileKey, nodeId as string)
            console.log('Successfully fetched Figma image')
          } catch (figmaError) {
            Logger.error('Failed to fetch Figma image:', figmaError)
            return {
              isError: true,
              content: [{ type: 'text', text: `Error fetching Figma image: ${figmaError instanceof Error ? figmaError.message : JSON.stringify(figmaError)}` }],
            }
          }
    
          let screenshotImg
          try {
            screenshotImg = await screenshotService.takeScreenshot(url)
            console.log('Successfully captured screenshot')
          } catch (screenshotError) {
            Logger.error('Failed to take screenshot:', screenshotError)
            return {
              isError: true,
              content: [{ type: 'text', text: `Error taking screenshot of ${url}: ${screenshotError instanceof Error ? screenshotError.message : JSON.stringify(screenshotError)}` }],
            }
          }
    
          // 处理图片转换,添加错误处理
          let figmaImgData
          let screenshotImgData
    
          try {
            figmaImgData = await imageContent({
              url: figmaImg,
            })
            console.log('Successfully converted Figma image')
          } catch (figmaConvertError) {
            Logger.error('Failed to convert Figma image:', figmaConvertError)
            return {
              isError: true,
              content: [{ type: 'text', text: `Error converting Figma image: ${figmaConvertError instanceof Error ? figmaConvertError.message : JSON.stringify(figmaConvertError)}` }],
            }
          }
    
          try {
            screenshotImgData = await imageContent({
              buffer: screenshotImg,
            })
            console.log('Successfully converted screenshot image')
          } catch (screenshotConvertError) {
            Logger.error('Failed to convert screenshot image:', screenshotConvertError)
            return {
              isError: true,
              content: [{ type: 'text', text: `Error converting screenshot image: ${screenshotConvertError instanceof Error ? screenshotConvertError.message : JSON.stringify(screenshotConvertError)}` }],
            }
          }
    
          // console.log('figmaImgData', figmaImgData)
          console.log('screenshotImgData', screenshotImgData)
    
          const prompt = similarityPrompt
    
          return {
            content: [
              { type: 'text', text: prompt },
              figmaImgData,
              screenshotImgData,
            ],
          }
        } catch (error) {
          const message = error instanceof Error ? error.message : JSON.stringify(error)
          Logger.error(`Error fetching file ${fileKey}:`, message)
          return {
            isError: true,
            content: [{ type: 'text', text: `Error fetching file: ${message}` }],
          }
        }
      },
    })
  • src/server.ts:39-39 (registration)
    Top-level registration call in the main MCP server that invokes SimilarityTools.registerTools() to add the tool.
    this.similarityTools.registerTools()
  • takeScreenshot method from ScreenshotService class, used in the handler to capture screenshot of the provided project URL using Puppeteer.
    async takeScreenshot(url: string, options?: {
      fileName?: string
      fullPage?: boolean
      width?: number
      height?: number
      timeout?: number
    }) {
    
      const browser = await puppeteer.launch({
        headless: true,
        executablePath: await this.getChromeExecutablePath(),
        args: ['--no-sandbox', '--disable-setuid-sandbox']
      })
    
      try {
        // 创建新页面
        const page = await browser.newPage()
    
        // 设置视口大小
        await page.setViewport({
          width: 375,
          height: 0,
        })
    
        // 导航到指定URL,等待网络空闲
        await page.goto(url, {
          timeout: options?.timeout || 30000,
          waitUntil: 'networkidle0',
        })
    
        // 执行截图
        const imageBuffer = await page.screenshot({
          fullPage: options?.fullPage || false,
        })
    
        // 将 Uint8Array 转换为 Buffer
        const buffer = Buffer.from(imageBuffer)
    
        // const imageBufferStr = buffer.toString('base64')
        // console.log('imageBufferStr', imageBufferStr)
    
        return buffer
      } finally {
        // 确保浏览器关闭
        await browser.close()
      }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions fetching prototypes and performing similarity comparisons, but fails to describe critical behaviors: whether this is a read-only operation, what the output format is (e.g., similarity score, visual report), how comparisons are conducted, or any rate limits/authentication needs. The description is insufficient for a tool with complex functionality.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence in Chinese that conveys the core purpose without unnecessary words. However, it could be more front-loaded by explicitly stating the tool's primary action (e.g., 'Compare Figma prototypes with code page screenshots for similarity') before detailing the process.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no annotations, no output schema, and complex functionality involving fetching and comparison, the description is incomplete. It lacks details on the comparison mechanism, output format, error handling, and how results should be interpreted. Given the context signals, the description should provide more guidance to help the agent use the tool effectively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, providing clear documentation for all three parameters. The description adds no additional parameter semantics beyond what's in the schema—it doesn't explain how 'url' relates to the comparison process or provide examples of valid inputs. Given the high schema coverage, a baseline score of 3 is appropriate, as the description doesn't compensate but doesn't detract either.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the tool '获取Figma原型图' (gets Figma prototypes) and mentions similarity comparison with generated code pages, but it's vague about the specific action. It doesn't clearly distinguish this from sibling tools like 'Download-Figma-Images' or 'Figma-To-Code', leaving ambiguity about whether it fetches images, performs analysis, or generates comparison reports.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives is provided. The description implies usage for comparing prototypes with code pages, but it doesn't specify prerequisites (e.g., needing project source code or screenshots), exclusions, or recommend other tools like 'Figma-To-Code' for different scenarios. This leaves the agent guessing about appropriate contexts.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

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/Panzer-Jack/feuse-mcp'

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