Skip to main content
Glama

get_figma_styles

Extract style data and CSS from Figma design nodes using file URLs to analyze design elements and retrieve visual properties.

Instructions

根据Figma URL获取节点的样式数据

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesFigma文件URL,可以包含node-id参数指定特定节点
generateCSSNo是否生成CSS代码

Implementation Reference

  • Core handler that parses Figma URL, fetches file and node, extracts relevant styled nodes, and computes style data for the get_figma_styles tool.
    async getStylesFromUrl(figmaUrl: string): Promise<ComponentStyles> {
      try {
        const urlInfo = this.figmaService.parseUrl(figmaUrl);
        const { fileId, nodeId } = urlInfo;
    
        const file = await this.figmaService.getFile(fileId);
        
        let targetNodes: FigmaNode[] = [];
    
        if (nodeId) {
          // 获取特定节点
          const node = await this.figmaService.getNode(fileId, nodeId);
          if (node) {
            targetNodes = [node];
          }
        } else {
          // 获取整个文件的主要组件
          targetNodes = this.extractMainComponents(file.document);
        }
    
        const styles = targetNodes.map(node => this.extractNodeStyle(node));
    
        return {
          fileInfo: {
            fileId,
            fileName: file.name,
            lastModified: file.lastModified,
          },
          styles,
          globalStyles: file.styles,
        };
      } catch (error) {
        throw new Error(`获取样式数据失败: ${error instanceof Error ? error.message : '未知错误'}`);
      }
    }
  • Tool dispatch handler in switch statement that calls the style extractor and formats response, optionally generating CSS.
    private async handleGetStyles(args: any) {
      const { url, generateCSS = false } = args;
    
      const styleData = await this.styleExtractor.getStylesFromUrl(url);
    
      let cssCode = '';
      if (generateCSS && styleData.styles.length > 0) {
        const cssRules = styleData.styles.map(style => {
          const selector = `.${style.nodeName.toLowerCase().replace(/\\s+/g, '-')}`;
          const css = this.styleExtractor.generateCSS(style);
          return css ? `${selector} {\\n  ${css}\\n}` : '';
        }).filter(rule => rule);
    
        cssCode = cssRules.join('\\n\\n');
      }
    
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify({
              success: true,
              data: {
                fileInfo: styleData.fileInfo,
                styles: styleData.styles,
                globalStyles: styleData.globalStyles,
                ...(cssCode && { generatedCSS: cssCode }),
              },
            }, null, 2),
          },
        ],
      };
    }
  • src/index.ts:75-93 (registration)
    Tool registration including name, description, and input schema in the ListTools response.
    {
      name: 'get_figma_styles',
      description: '根据Figma URL获取节点的样式数据',
      inputSchema: {
        type: 'object',
        properties: {
          url: {
            type: 'string',
            description: 'Figma文件URL,可以包含node-id参数指定特定节点',
          },
          generateCSS: {
            type: 'boolean',
            description: '是否生成CSS代码',
            default: false,
          },
        },
        required: ['url'],
      },
    },
  • Type definitions for style data structures used as output schema for the tool.
    export interface StyleData {
      nodeId: string;
      nodeName: string;
      nodeType: string;
      position?: {
        x: number;
        y: number;
        width: number;
        height: number;
      };
      fills?: Array<{
        type: string;
        color?: {
          r: number;
          g: number;
          b: number;
          a: number;
        };
        gradientStops?: Array<{
          color: { r: number; g: number; b: number; a: number };
          position: number;
        }>;
      }>;
      strokes?: Array<{
        type: string;
        color?: {
          r: number;
          g: number;
          b: number;
          a: number;
        };
      }>;
      strokeWeight?: number;
      cornerRadius?: number;
      effects?: Array<{
        type: string;
        visible: boolean;
        radius?: number;
        color?: {
          r: number;
          g: number;
          b: number;
          a: number;
        };
        offset?: {
          x: number;
          y: number;
        };
      }>;
      textStyle?: {
        fontFamily?: string;
        fontSize?: number;
        fontWeight?: number;
        letterSpacing?: number;
        lineHeight?: number;
        textAlign?: string;
        textColor?: {
          r: number;
          g: number;
          b: number;
          a: number;
        };
      };
      constraints?: {
        vertical: string;
        horizontal: string;
      };
    }
    
    export interface ComponentStyles {
      fileInfo: {
        fileId: string;
        fileName: string;
        lastModified: string;
      };
      styles: StyleData[];
      globalStyles?: Record<string, any>;
    }
  • Helper function to generate CSS from extracted style data, used when generateCSS=true.
    generateCSS(styleData: StyleData): string {
      const cssRules: string[] = [];
    
      // 位置和尺寸
      if (styleData.position) {
        cssRules.push(`width: ${styleData.position.width}px`);
        cssRules.push(`height: ${styleData.position.height}px`);
      }
    
      // 背景色
      if (styleData.fills && styleData.fills.length > 0) {
        const fill = styleData.fills[0];
        if (fill.color) {
          const { r, g, b, a } = fill.color;
          if (a === 1) {
            cssRules.push(`background-color: rgb(${r}, ${g}, ${b})`);
          } else {
            cssRules.push(`background-color: rgba(${r}, ${g}, ${b}, ${a})`);
          }
        }
      }
    
      // 边框
      if (styleData.strokes && styleData.strokes.length > 0) {
        const stroke = styleData.strokes[0];
        const weight = styleData.strokeWeight || 1;
        if (stroke.color) {
          const { r, g, b, a } = stroke.color;
          if (a === 1) {
            cssRules.push(`border: ${weight}px solid rgb(${r}, ${g}, ${b})`);
          } else {
            cssRules.push(`border: ${weight}px solid rgba(${r}, ${g}, ${b}, ${a})`);
          }
        }
      }
    
      // 圆角
      if (styleData.cornerRadius !== undefined) {
        cssRules.push(`border-radius: ${styleData.cornerRadius}px`);
      }
    
      // 文本样式
      if (styleData.textStyle) {
        const textStyle = styleData.textStyle;
        if (textStyle.fontFamily) {
          cssRules.push(`font-family: "${textStyle.fontFamily}"`);
        }
        if (textStyle.fontSize) {
          cssRules.push(`font-size: ${textStyle.fontSize}px`);
        }
        if (textStyle.fontWeight) {
          cssRules.push(`font-weight: ${textStyle.fontWeight}`);
        }
        if (textStyle.letterSpacing) {
          cssRules.push(`letter-spacing: ${textStyle.letterSpacing}px`);
        }
        if (textStyle.lineHeight) {
          cssRules.push(`line-height: ${textStyle.lineHeight}px`);
        }
        if (textStyle.textAlign) {
          cssRules.push(`text-align: ${textStyle.textAlign.toLowerCase()}`);
        }
        if (textStyle.textColor) {
          const { r, g, b, a } = textStyle.textColor;
          if (a === 1) {
            cssRules.push(`color: rgb(${r}, ${g}, ${b})`);
          } else {
            cssRules.push(`color: rgba(${r}, ${g}, ${b}, ${a})`);
          }
        }
      }
    
      // 阴影效果
      if (styleData.effects && styleData.effects.length > 0) {
        const shadows = styleData.effects
          .filter(effect => effect.type === 'DROP_SHADOW' && effect.visible)
          .map(effect => {
            const x = effect.offset?.x || 0;
            const y = effect.offset?.y || 0;
            const blur = effect.radius || 0;
            if (effect.color) {
              const { r, g, b, a } = effect.color;
              return `${x}px ${y}px ${blur}px rgba(${r}, ${g}, ${b}, ${a})`;
            }
            return '';
          })
          .filter(shadow => shadow);
    
        if (shadows.length > 0) {
          cssRules.push(`box-shadow: ${shadows.join(', ')}`);
        }
      }
    
      return cssRules.length > 0 ? cssRules.join(';\n  ') + ';' : '';
    }

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/Echoxiawan/figma-mcp-full-server'

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