resources.ts•4.58 kB
/**
 * Resources for the Figma MCP server
 */
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import figmaApi from "./services/figma-api.js";
/**
 * Resource template for Figma files
 */
export const figmaFileResource = (server: McpServer): void => {
  server.resource(
    "figma-file",
    new ResourceTemplate("figma-file://{file_key}", {
      // Define listCallback instead of just providing a string for 'list'
      listCallback: async () => {
        try {
          // Here we would typically get a list of files
          // For now, return an empty list since we don't have access to "all files"
          return {
            contents: [{
              uri: "figma-file://",
              title: "Figma Files",
              description: "List of Figma files you have access to",
              text: "# Figma Files\n\nTo access a specific file, you need to provide its file key."
            }]
          };
        } catch (error) {
          console.error('Error listing files:', error);
          return {
            contents: [{
              uri: "figma-file://",
              title: "Error listing files",
              text: `Error: ${(error as Error).message}`
            }]
          };
        }
      }
    }),
    async (uri, { file_key }) => {
      try {
        const file = await figmaApi.getFile(file_key);
        
        return {
          contents: [{
            uri: uri.href,
            title: file.name,
            description: `Last modified: ${file.lastModified}`,
            text: `# ${file.name}\n\nLast modified: ${file.lastModified}\n\nDocument contains ${file.document.children?.length || 0} top-level nodes.\nComponents: ${Object.keys(file.components).length}\nStyles: ${Object.keys(file.styles).length}`
          }]
        };
      } catch (error) {
        console.error('Error fetching file for resource:', error);
        return {
          contents: [{
            uri: uri.href,
            title: `File not found: ${file_key}`,
            text: `Error: ${(error as Error).message}`
          }]
        };
      }
    }
  );
};
/**
 * Resource template for Figma nodes
 */
export const figmaNodeResource = (server: McpServer): void => {
  server.resource(
    "figma-node",
    new ResourceTemplate("figma-node://{file_key}/{node_id}", {
      // Define listCallback instead of just providing a string for 'list'
      listCallback: async (uri, { file_key }) => {
        try {
          // If only file_key is provided, list all top-level nodes
          const file = await figmaApi.getFile(file_key);
          
          return {
            contents: file.document.children?.map(node => ({
              uri: `figma-node://${file_key}/${node.id}`,
              title: node.name,
              description: `Type: ${node.type}`,
              text: `# ${node.name}\n\nType: ${node.type}\nID: ${node.id}`
            })) || []
          };
        } catch (error) {
          console.error('Error listing nodes:', error);
          return {
            contents: [{
              uri: `figma-node://${file_key}`,
              title: "Error listing nodes",
              text: `Error: ${(error as Error).message}`
            }]
          };
        }
      }
    }),
    async (uri, { file_key, node_id }) => {
      try {
        // Get specific node
        const fileNodes = await figmaApi.getFileNodes(file_key, [node_id]);
        const nodeData = fileNodes.nodes[node_id];
        
        if (!nodeData) {
          return {
            contents: [{
              uri: uri.href,
              title: `Node not found: ${node_id}`,
              text: `Node ${node_id} not found in file ${file_key}`
            }]
          };
        }
        
        return {
          contents: [{
            uri: uri.href,
            title: nodeData.document.name,
            description: `Type: ${nodeData.document.type}`,
            text: `# ${nodeData.document.name}\n\nType: ${nodeData.document.type}\nID: ${nodeData.document.id}\nChildren: ${nodeData.document.children?.length || 0}`
          }]
        };
      } catch (error) {
        console.error('Error fetching node for resource:', error);
        return {
          contents: [{
            uri: uri.href,
            title: `Error`,
            text: `Error: ${(error as Error).message}`
          }]
        };
      }
    }
  );
};
/**
 * Registers all resources with the MCP server
 */
export function registerAllResources(server: McpServer): void {
  figmaFileResource(server);
  figmaNodeResource(server);
}