#
tokens: 6355/50000 10/10 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── .gitignore
├── dockerfile
├── package-lock.json
├── package.json
├── README.md
├── src
│   ├── figma-api.ts
│   ├── index.ts
│   ├── prompts.ts
│   ├── resources.ts
│   └── tools.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
# Dependencies
node_modules/
npm-debug.log
yarn-debug.log
yarn-error.log

# Build outputs
build/
dist/
*.tsbuildinfo

# Environment variables
.env
.env.local
.env.development
.env.test
.env.production

# IDE and editor files
.idea/
.vscode/
*.swp
*.swo
.DS_Store

# Logs
logs/
*.log

# Coverage reports
coverage/

# Temporary files
tmp/
temp/
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# Figma MCP Server

A Model Context Protocol (MCP) server that connects to Figma's API, allowing AI tools and LLMs to access and work with your Figma designs.



## Features

- **Design Data Extraction**: Extract components, styles, and text from your Figma designs
- **Design System Analysis**: Analyze design system consistency and patterns
- **UI Content Management**: Extract and organize all UI copy from designs
- **Development Handoff**: Generate comprehensive documentation for developers
- **Seamless AI Integration**: Connect your designs to AI tools like Claude, Cursor, and other MCP-compatible clients

## Getting Started

### Prerequisites

- Node.js 16 or higher
- Figma Personal Access Token (Get it from your Figma account settings)

### Installation

1. Clone the repository:
   ```bash
   git clone https://github.com/yourusername/figma-mcp-server.git
   cd figma-mcp-server
   ```

2. Install dependencies:
   ```bash
   npm install
   ```

3. Create a `.env` file in the project root:
   ```
   FIGMA_API_TOKEN=your_figma_personal_access_token
   API_KEY=your_secure_api_key
   TRANSPORT_TYPE=stdio
   ```

4. Build the server:
   ```bash
   npm run build
   ```

5. Start the server:
   ```bash
   npm start
   ```



## Connecting to Clients

### Claude for Desktop

1. Open or create the Claude for Desktop configuration file:
   - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
   - Windows: `%APPDATA%\Claude\claude_desktop_config.json`

2. Add the following configuration:
   ```json
   {
     "mcpServers": {
       "figma": {
         "command": "node",
         "args": ["/absolute/path/to/figma-mcp-server/build/index.js"],
         "env": {
           "FIGMA_API_TOKEN": "your_figma_personal_access_token",
           "TRANSPORT_TYPE": "stdio"
         }
       }
     }
   }
   ```

3. Restart Claude for Desktop

### Cursor

#### Global Configuration

Create or edit Cursor's MCP configuration file:
- macOS: `~/Library/Application Support/Cursor/mcp.json`
- Windows: `%APPDATA%\Cursor\mcp.json`

```json
{
  "mcpServers": {
    "figma-mcp": {
      "url": "http://localhost:3000/sse",
      "env": {
        "API_KEY": "your_secure_api_key"
      }
    }
  }
}
```

#### Project-Specific Configuration

1. Create a `.cursor` directory in your project root:
   ```bash
   mkdir -p .cursor
   ```

2. Create an `mcp.json` file inside that directory:
   ```json
   {
     "mcpServers": {
       "figma-mcp": {
         "url": "http://localhost:3000/sse",
         "env": {
           "API_KEY": "your_secure_api_key"
         }
       }
     }
   }
   ```

## Available Tools

| Tool | Description |
|------|-------------|
| `get-file-info` | Get basic information about a Figma file |
| `get-nodes` | Get specific nodes from a Figma file |
| `get-components` | Get component information from a Figma file |
| `get-styles` | Get style information from a Figma file |
| `get-comments` | Get comments from a Figma file |
| `search-file` | Search for elements in a Figma file by type, name, etc. |
| `extract-text` | Extract all text elements from a Figma file |



## Available Prompts

- `analyze-design-system` - Analyze design system components and styles for consistency
- `extract-ui-copy` - Extract and organize all UI copy from designs
- `generate-dev-handoff` - Generate development handoff documentation based on designs

## Usage Examples

Using with Claude:
```
Can you analyze the design system in my Figma file with key abc123? Look for consistency in color usage and typography.
```

Using with Cursor:
```
Generate React components for the buttons from my Figma file with key abc123, using tailwind CSS.
```

## Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `FIGMA_API_TOKEN` | Your Figma Personal Access Token | (Required) |
| `API_KEY` | Security key for API authentication | (Required) |
| `TRANSPORT_TYPE` | Transport method (`stdio` or `sse`) | `stdio` |
| `PORT` | Port for SSE transport | `3000` |

## Architecture

This MCP server:
1. Connects to the Figma API using your personal access token
2. Exposes a standardized interface following the Model Context Protocol
3. Provides tools, resources, and prompts that LLMs can use to interact with your Figma designs
4. Supports both stdio transport (local connections) and SSE transport (remote connections)

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.


```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
    "compilerOptions": {
      "target": "ES2022",
      "module": "Node16",
      "moduleResolution": "Node16",
      "outDir": "./build",
      "rootDir": "./src",
      "strict": true,
      "esModuleInterop": true,
      "skipLibCheck": true,
      "forceConsistentCasingInFileNames": true
    },
    "include": ["src/**/*"],
    "exclude": ["node_modules"]
  }
```

--------------------------------------------------------------------------------
/dockerfile:
--------------------------------------------------------------------------------

```dockerfile
FROM node:18-alpine

WORKDIR /app

# Copy package files and install dependencies
COPY package*.json ./
RUN npm ci --only=production

# Copy the built app
COPY build/ ./build/

# Set environment variables (placeholder values to be overridden at runtime)
ENV FIGMA_API_TOKEN=""
ENV TRANSPORT_TYPE="sse"
ENV PORT=3000
ENV API_KEY=""

# Expose the port
EXPOSE 3000

# Run the server
CMD ["node", "build/index.js"]
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "figma-mcp-server",
  "version": "1.0.0",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "build": "tsc",
    "start": "node build/index.js",
    "dev": "tsc && node build/index.js",
    "start:stdio": "TRANSPORT_TYPE=stdio node build/index.js",
    "start:sse": "TRANSPORT_TYPE=sse node build/index.js"
  },
  "keywords": [
    "figma",
    "mcp",
    "design"
  ],
  "author": "Mohammed-uvaiz",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.7.0",
    "cors": "^2.8.5",
    "dotenv": "^16.4.7",
    "express": "^5.0.1",
    "node-fetch": "^3.3.2",
    "zod": "^3.24.2"
  },
  "devDependencies": {
    "@types/cors": "^2.8.17",
    "@types/express": "^5.0.0",
    "@types/node": "^22.13.10",
    "typescript": "^5.8.2"
  }
}

```

--------------------------------------------------------------------------------
/src/figma-api.ts:
--------------------------------------------------------------------------------

```typescript
import fetch from "node-fetch";
import dotenv from "dotenv";
dotenv.config();

// Base URL for Figma API
export const FIGMA_API_BASE_URL = "https://api.figma.com/v1";


// Check if Figma API token is available
const FIGMA_API_TOKEN = process.env.FIGMA_API_TOKEN;
if (!FIGMA_API_TOKEN) {
  console.error("Error: FIGMA_API_TOKEN environment variable is required");
  process.exit(1);
}

/**
 * Helper function to make authenticated requests to Figma API
 * @param endpoint API endpoint path (without base URL)
 * @returns Promise with JSON response
 */
export async function fetchFigmaAPI(endpoint: string) {
  const response = await fetch(`${FIGMA_API_BASE_URL}${endpoint}`, {
    headers: {
      "X-Figma-Token": FIGMA_API_TOKEN as string
    }
  });

  if (!response.ok) {
    throw new Error(`Figma API error: ${response.status} ${response.statusText}`);
  }

  return response.json();
}

/**
 * Helper function to recursively search through nodes by criteria
 * @param node The node to search from
 * @param query The search query string
 * @returns Array of matching nodes
 */
export function searchNodes(node: any, query: string, results: any[] = []) {
  // Check if this node matches search criteria
  if (node.name && node.name.toLowerCase().includes(query.toLowerCase())) {
    results.push({
      id: node.id,
      name: node.name,
      type: node.type,
      path: [node.name]
    });
  }
  
  // Recursively search child nodes if they exist
  if (node.children && node.children.length > 0) {
    for (const child of node.children) {
      searchNodes(child, query, results);
    }
  }
  
  return results;
}

/**
 * Helper function to recursively find text nodes
 * @param node The node to search from
 * @returns Array of text nodes
 */
export function findTextNodes(node: any, results: any[] = []) {
  if (node.type === "TEXT") {
    results.push({
      id: node.id,
      name: node.name,
      characters: node.characters,
      style: node.style
    });
  }
  
  // Recursively search child nodes if they exist
  if (node.children && node.children.length > 0) {
    for (const child of node.children) {
      findTextNodes(child, results);
    }
  }
  
  return results;
}
```

--------------------------------------------------------------------------------
/src/prompts.ts:
--------------------------------------------------------------------------------

```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

/**
 * Register all Figma-related prompts with the MCP server
 * @param server The MCP server instance
 */
export function registerPrompts(server: McpServer) {
  // Prompt to analyze design system consistency
  server.prompt(
    "analyze-design-system",
    "Analyze design system components and styles for consistency",
    {
      fileKey: z.string().describe("The Figma file key")
    },
    ({ fileKey }) => ({
      messages: [{
        role: "user",
        content: {
          type: "text",
          text: `Please analyze the design system in this Figma file (${fileKey}). 
          Focus on color consistency, typography usage, component variations, and 
          any inconsistencies or opportunities for improvement. First list the components 
          and styles using the appropriate tools, then provide your analysis.`
        }
      }]
    })
  );

  // Prompt to extract UI copy
  server.prompt(
    "extract-ui-copy",
    "Extract and organize all UI copy from designs",
    {
      fileKey: z.string().describe("The Figma file key")
    },
    ({ fileKey }) => ({
      messages: [{
        role: "user",
        content: {
          type: "text",
          text: `Please extract all UI copy from this Figma file (${fileKey}).
          Organize the text by screens or components, and identify any potential 
          inconsistencies in tone, terminology, or language. 
          Use the extract-text tool to get the content.`
        }
      }]
    })
  );

  // Prompt to generate development handoff documentation
  server.prompt(
    "generate-dev-handoff",
    "Generate development handoff documentation based on designs",
    {
      fileKey: z.string().describe("The Figma file key")
    },
    ({ fileKey }) => ({
      messages: [{
        role: "user",
        content: {
          type: "text",
          text: `Please create comprehensive development handoff documentation for this Figma file (${fileKey}).
          Include component specifications, style guides, interaction patterns, and responsive behavior descriptions.
          Use the appropriate tools to gather file data, components, and styles.`
        }
      }]
    })
  );
}
```

--------------------------------------------------------------------------------
/src/resources.ts:
--------------------------------------------------------------------------------

```typescript
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { fetchFigmaAPI } from "./figma-api.js";

interface ComponentsResponse {
    meta: {
      components: unknown[];
    };
  }
  interface StylesResponse {
    meta: {
      styles: unknown[];
    };
  }
  
/**
 * Register all Figma-related resources with the MCP server
 * @param server The MCP server instance
 */
export function registerResources(server: McpServer) {
  // Resource to list Figma files a user has access to
  server.resource(
    "user-files",
    "figma://files",
    async (uri) => {
      try {
        const filesData = await fetchFigmaAPI(`/me/files`);
        
        return {
          contents: [{
            uri: uri.href,
            text: JSON.stringify(filesData, null, 2)
          }]
        };
      } catch (error) {
        throw new Error(`Error fetching Figma files: ${error instanceof Error ? error.message : String(error)}`);
      }
    }
  );

  // Resource to list projects
  server.resource(
    "projects",
    "figma://projects",
    async (uri) => {
      try {
        const projectsData = await fetchFigmaAPI(`/me/projects`);
        
        return {
          contents: [{
            uri: uri.href,
            text: JSON.stringify(projectsData, null, 2)
          }]
        };
      } catch (error) {
        throw new Error(`Error fetching Figma projects: ${error instanceof Error ? error.message : String(error)}`);
      }
    }
  );

  // Resource to get file data
  server.resource(
    "file-data",
    new ResourceTemplate("figma://{fileKey}/data", { list: undefined }),
    async (uri, { fileKey }) => {
      try {
        const fileData = await fetchFigmaAPI(`/files/${fileKey}`);
        
        return {
          contents: [{
            uri: uri.href,
            text: JSON.stringify(fileData, null, 2)
          }]
        };
      } catch (error) {
        throw new Error(`Error fetching Figma file data: ${error instanceof Error ? error.message : String(error)}`);
      }
    }
  );

  // Resource to get design system metadata
  server.resource(
    "design-system",
    new ResourceTemplate("figma://{fileKey}/design-system", { list: undefined }),
    async (uri, { fileKey }) => {
      try {
        // Get components and styles in parallel
        const [componentsData, stylesData] = await Promise.all([
          fetchFigmaAPI(`/files/${fileKey}/components`) as Promise<ComponentsResponse>,
          fetchFigmaAPI(`/files/${fileKey}/styles`) as Promise<StylesResponse>
        ]);
        
        const designSystem = {
          components: componentsData.meta.components,
          styles: stylesData.meta.styles
        };
        
        return {
          contents: [{
            uri: uri.href,
            text: JSON.stringify(designSystem, null, 2)
          }]
        };
      } catch (error) {
        throw new Error(`Error fetching design system data: ${error instanceof Error ? error.message : String(error)}`);
      }
    }
  );
}
```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import express from "express";
import cors from "cors";
import dotenv from "dotenv";

// Import our components
import { registerTools } from "./tools.js";
import { registerResources } from "./resources.js";
import { registerPrompts } from "./prompts.js";

// Load environment variables
console.error("Loading environment variables...");
dotenv.config();
console.error("Environment loaded. FIGMA_API_TOKEN present:", process.env.FIGMA_API_TOKEN ? "Yes" : "No");

// Check token before proceeding
if (!process.env.FIGMA_API_TOKEN) {
  console.error("ERROR: FIGMA_API_TOKEN environment variable is required!");
  process.exit(1);
}

async function main() {
  try {
    console.error("===== FIGMA MCP SERVER STARTING =====");
    
    // Create the MCP server
    console.error("Creating MCP server instance...");
    const server = new McpServer({
      name: "figma-mcp-server",
      version: "1.0.0"
    });
    console.error("MCP server instance created successfully");

    // Register all components
    console.error("Registering tools...");
    registerTools(server);
    console.error("Registering resources...");
    registerResources(server);
    console.error("Registering prompts...");
    registerPrompts(server);
    console.error("All components registered successfully");

    // Determine transport type based on environment
    const transportType = process.env.TRANSPORT_TYPE || "stdio";
    console.error(`Using transport type: ${transportType}`);

    if (transportType === "stdio") {
      // Use stdio transport for local connections
      console.error("Creating StdioServerTransport...");
      const transport = new StdioServerTransport();
      console.error("Connecting server to stdio transport...");
      await server.connect(transport);
      console.error("Successfully connected to stdio transport");
    } else if (transportType === "sse") {
      // Use SSE transport for remote connections
      console.error("Starting web server for SSE transport...");
      
      const app = express();
      const port = process.env.PORT || 3000;
      
    // Add CORS support
      app.use(cors()); 
    // Parse JSON bodies
      app.use(express.json());
    // ADD AUTHENTICATION HERE
      const API_KEY = process.env.API_KEY || "default-key-please-change";

    // Middleware to check for API key
      const authenticateApiKey = (req: express.Request, res: express.Response, next: express.NextFunction): void => {
      const providedKey = req.headers['x-api-key'];
  
       if (!providedKey || providedKey !== API_KEY) {
         res.status(401).json({ error: "Unauthorized" });
         return;
    }
  
    next();
};
      // Add a basic home page
      app.get("/", (req, res) => {
        res.send("Figma MCP Server - Status: Running");
      });
      
      // Health check endpoint
      app.get("/health", (req, res) => {
        res.json({ status: "ok", version: "1.0.0" });
      });
      
      // Map to store active transports
      const activeTransports = new Map();
      
      // SSE endpoint
      app.get("/sse",authenticateApiKey, (req, res) => {
        console.error("New SSE connection request received");
        const clientId = Date.now().toString();
        
        res.setHeader("Content-Type", "text/event-stream");
        res.setHeader("Cache-Control", "no-cache");
        res.setHeader("Connection", "keep-alive");
        
        // Create a new transport for this connection
        const transport = new SSEServerTransport("/messages", res);
        activeTransports.set(clientId, transport);
        
        console.error(`SSE connection established for client ${clientId}`);
        
        // Connect the server to this transport
        server.connect(transport).catch(err => {
          console.error(`Error connecting to transport for client ${clientId}:`, err);
        });
        
        // Handle client disconnect
        req.on("close", () => {
          console.error(`Client ${clientId} disconnected`);
          activeTransports.delete(clientId);
        });
      });
      
      // Message endpoint for client-to-server communication
      app.post("/messages", authenticateApiKey,async (req, res) => {
        console.error("Received message from client");
        
        // Find the active transport
        // Note: In a real implementation, you'd need a way to identify 
        // which transport to use based on the client
        
        if (activeTransports.size > 0) {
          const transport = Array.from(activeTransports.values())[0];
          await transport.handlePostMessage(req, res);
        } else {
          res.status(400).json({ error: "No active connections" });
        }
      });
      
      // Start the server
      app.listen(port, () => {
        console.error(`Web server running on port ${port}`);
      });
    } else {
      console.error(`Unknown transport type: ${transportType}`);
      process.exit(1);
    }

    console.error("===== FIGMA MCP SERVER RUNNING =====");
    
  } catch (error) {
    console.error("FATAL SERVER ERROR:");
    console.error(error);
    process.exit(1);
  }
}

// Run the server
console.error("Calling main()...");
main().catch(error => {
  console.error("Unhandled error in main():", error);
  process.exit(1);
});
```

--------------------------------------------------------------------------------
/src/tools.ts:
--------------------------------------------------------------------------------

```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { fetchFigmaAPI, searchNodes, findTextNodes } from "./figma-api.js";

interface FigmaFileResponse {
  name: string;
  lastModified: string;
  version: string;
  document: {
    id: string;
    name: string;
    type: string;
  };
  schemaVersion: number;
  thumbnailUrl: string;
}


export function registerTools(server: McpServer) {
  // Tool to get file information
  server.tool(
    "get-file-info",
    "Get basic information about a Figma file",
    {
      fileKey: z.string().describe("The Figma file key (found in the file URL)")
    },
    async ({ fileKey }) => {
      try {
        const fileData = await fetchFigmaAPI(`/files/${fileKey}`) as FigmaFileResponse;
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify({
                name: fileData.name,
                lastModified: fileData.lastModified,
                version: fileData.version,
                document: {
                  id: fileData.document.id,
                  name: fileData.document.name,
                  type: fileData.document.type
                },
                schemaVersion: fileData.schemaVersion,
                thumbnailUrl: fileData.thumbnailUrl
              }, null, 2)
            }
          ]
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error fetching Figma file information: ${error instanceof Error ? error.message : String(error)}`
            }
          ],
          isError: true
        };
      }
    }
  );

  // Tool to get file nodes
  server.tool(
    "get-nodes",
    "Get specific nodes from a Figma file",
    {
      fileKey: z.string().describe("The Figma file key (found in the file URL)"),
      nodeIds: z.array(z.string()).describe("Array of node IDs to fetch")
    },
    async ({ fileKey, nodeIds }) => {
      try {
        const nodeIdsParam = nodeIds.join(",");
        const nodesData = await fetchFigmaAPI(`/files/${fileKey}/nodes?ids=${nodeIdsParam}`);
        
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(nodesData, null, 2)
            }
          ]
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error fetching Figma nodes: ${error instanceof Error ? error.message : String(error)}`
            }
          ],
          isError: true
        };
      }
    }
  );

  // Tool to get file component sets and components
  server.tool(
    "get-components",
    "Get component information from a Figma file",
    {
      fileKey: z.string().describe("The Figma file key (found in the file URL)")
    },
    async ({ fileKey }) => {
      try {
        const componentsData = await fetchFigmaAPI(`/files/${fileKey}/components`);
        
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(componentsData, null, 2)
            }
          ]
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error fetching Figma components: ${error instanceof Error ? error.message : String(error)}`
            }
          ],
          isError: true
        };
      }
    }
  );

  // Tool to get design system styles
  server.tool(
    "get-styles",
    "Get style information from a Figma file",
    {
      fileKey: z.string().describe("The Figma file key (found in the file URL)")
    },
    async ({ fileKey }) => {
      try {
        const stylesData = await fetchFigmaAPI(`/files/${fileKey}/styles`);
        
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(stylesData, null, 2)
            }
          ]
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error fetching Figma styles: ${error instanceof Error ? error.message : String(error)}`
            }
          ],
          isError: true
        };
      }
    }
  );

  // Tool to get comments from a Figma file
  server.tool(
    "get-comments",
    "Get comments from a Figma file",
    {
      fileKey: z.string().describe("The Figma file key (found in the file URL)")
    },
    async ({ fileKey }) => {
      try {
        const commentsData = await fetchFigmaAPI(`/files/${fileKey}/comments`);
        
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(commentsData, null, 2)
            }
          ]
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error fetching Figma comments: ${error instanceof Error ? error.message : String(error)}`
            }
          ],
          isError: true
        };
      }
    }
  );

  // Tool to search for specific elements in a Figma file
  server.tool(
    "search-file",
    "Search for elements in a Figma file by type, name, etc.",
    {
      fileKey: z.string().describe("The Figma file key (found in the file URL)"),
      query: z.string().describe("Search query")
    },
    async ({ fileKey, query }) => {
      try {
        // Fetch all file data first
        const fileData = await fetchFigmaAPI(`/files/${fileKey}`) as FigmaFileResponse;
        const searchResults = searchNodes(fileData.document, query);
        
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(searchResults, null, 2)
            }
          ]
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error searching Figma file: ${error instanceof Error ? error.message : String(error)}`
            }
          ],
          isError: true
        };
      }
    }
  );

  // Tool to extract text from a Figma file
  server.tool(
    "extract-text",
    "Extract all text elements from a Figma file",
    {
      fileKey: z.string().describe("The Figma file key (found in the file URL)")
    },
    async ({ fileKey }) => {
      try {
        // Fetch all file data first
        const fileData = await fetchFigmaAPI(`/files/${fileKey}`) as FigmaFileResponse;
        const textNodes = findTextNodes(fileData.document);
        
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(textNodes, null, 2)
            }
          ]
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error extracting text from Figma file: ${error instanceof Error ? error.message : String(error)}`
            }
          ],
          isError: true
        };
      }
    }
  );
}
```