Skip to main content
Glama
alucardeht
by alucardeht

search_components

Find Figma components by name across files or pages using partial matching, with filtering options to refine results and retrieve design assets efficiently.

Instructions

Search for components by name across the file.

HOW IT WORKS:

  • Searches entire file or specific page

  • Returns top 20 results with total count

  • If >20 results, suggests refinement options

  • Use 'continue: true' to get more results

TYPICAL WORKFLOW:

  1. search_components(query) → find matches

  2. If too many: refine with page_name or type filter

  3. get_frame_info on specific result

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
file_keyYesFigma file key
queryYesSearch term (case-insensitive, partial match)
page_nameNoLimit search to specific page
typeNoFilter by type: COMPONENT, INSTANCE, FRAME, TEXT, VECTOR
continueNoContinue from last response for more results

Implementation Reference

  • The core handler function that executes the search_components tool. Searches Figma file for nodes matching the query, handles pagination with continueFlag, and returns chunked results.
    export async function searchComponents(ctx, fileKey, query, pageName, type, continueFlag = false) { const { session, chunker, figmaClient } = ctx; const operationId = `search_components:${fileKey}:${query}:${pageName || "all"}:${type || "all"}`; if (continueFlag && session.hasPendingChunks(operationId)) { const chunk = session.getNextChunk(operationId); const response = chunker.wrapResponse( { query, results: chunk.items }, { step: `Showing results ${(chunk.chunkIndex - 1) * 20 + 1}-${Math.min(chunk.chunkIndex * 20, chunk.totalItems)}`, progress: `${chunk.chunkIndex}/${chunk.totalChunks}`, nextStep: chunk.chunkIndex < chunk.totalChunks ? "Call with continue=true for more" : "Use get_frame_info on specific result", operationId, } ); return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] }; } const file = await figmaClient.getFile(fileKey, 99); const lowerQuery = query.toLowerCase(); const results = []; const searchNode = (node, pageNameLocal, path) => { if (type && node.type !== type) { if (node.children) { node.children.forEach((child) => searchNode(child, pageNameLocal, [...path, node.name])); } return; } if (node.name.toLowerCase().includes(lowerQuery)) { results.push({ name: node.name, type: node.type, id: node.id, page: pageNameLocal, path: path.join(" > "), bounds: node.absoluteBoundingBox ? { width: Math.round(node.absoluteBoundingBox.width), height: Math.round(node.absoluteBoundingBox.height), } : null, }); } if (node.children) { node.children.forEach((child) => searchNode(child, pageNameLocal, [...path, node.name])); } }; const pages = pageName ? [figmaClient.findPageByName(file, pageName)].filter(Boolean) : file.document.children; pages.forEach((page) => { searchNode(page, page.name, []); }); if (results.length > 20) { const chunked = chunker.chunkArray(results, operationId, 20); const pageNames = [...new Set(results.map((r) => r.page))]; const types = [...new Set(results.map((r) => r.type))]; const response = chunker.wrapResponse( { query, resultCount: results.length, results: chunked.items }, { step: `Showing results 1-${chunked.items.length} of ${results.length}`, progress: `1/${chunked.totalChunks}`, nextStep: "Call with continue=true for more, or refine search", alert: `Found ${results.length} matches - showing first 20`, refinementOptions: [ pageNames.length > 1 ? `Filter by page: ${pageNames.slice(0, 3).join(", ")}` : null, types.length > 1 ? `Filter by type: ${types.join(", ")}` : null, "Use more specific search term", ].filter(Boolean), operationId, } ); return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] }; } const response = chunker.wrapResponse( { query, resultCount: results.length, results }, { step: "Search complete", progress: `${results.length} results`, nextStep: results.length > 0 ? "Use get_frame_info on a result for details" : "Try different search term", } ); return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] }; }
  • Input schema and description for the search_components tool, defining parameters and behavior.
    { name: "search_components", description: `Search for components by name across the file. HOW IT WORKS: - Searches entire file or specific page - Returns top 20 results with total count - If >20 results, suggests refinement options - Use 'continue: true' to get more results TYPICAL WORKFLOW: 1. search_components(query) → find matches 2. If too many: refine with page_name or type filter 3. get_frame_info on specific result`, inputSchema: { type: "object", properties: { file_key: { type: "string", description: "Figma file key" }, query: { type: "string", description: "Search term (case-insensitive, partial match)" }, page_name: { type: "string", description: "Limit search to specific page" }, type: { type: "string", description: "Filter by type: COMPONENT, INSTANCE, FRAME, TEXT, VECTOR" }, continue: { type: "boolean", description: "Continue from last response for more results" }, }, required: ["file_key", "query"], }, },
  • src/index.js:63-65 (registration)
    Dispatches calls to the search_components tool handler in the main MCP server switch statement.
    case "search_components": result = await handlers.searchComponents(this.ctx, args.file_key, args.query, args.page_name, args.type, args.continue); break;
  • Re-exports the searchComponents handler for use in the main index.js.
    export { searchComponents } from "./search.js";

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/alucardeht/figma-mcp'

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