figma-mcp-server 2.0.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -2
- package/README.md +37 -11
- package/bun.lock +80 -34
- package/commands/tools.ts +87 -0
- package/{index.js → index.ts} +2 -2
- package/lib/tools.ts +38 -0
- package/mcpServer.ts +186 -0
- package/package.json +22 -12
- package/preview.webp +0 -0
- package/tools/figma/figma-api/{create-dev-resources-for-a-file.js → create-dev-resources-for-a-file.ts} +9 -11
- package/tools/figma/figma-api/{create-variable-collections-for-a-file.js → create-variable-collections-for-a-file.ts} +7 -9
- package/tools/figma/figma-api/{get-a-published-component-by-key.js → get-a-published-component-by-key.ts} +7 -9
- package/tools/figma/figma-api/{get-a-published-component-set-by-key.js → get-a-published-component-set-by-key.ts} +7 -9
- package/tools/figma/figma-api/{get-a-published-library-by-id.js → get-a-published-library-by-id.ts} +7 -9
- package/tools/figma/figma-api/{get-a-published-style-by-key.js → get-a-published-style-by-key.ts} +7 -9
- package/tools/figma/figma-api/{get-current-user.js → get-current-user.ts} +6 -8
- package/tools/figma/figma-api/{get-file-nodes.js → get-file-nodes.ts} +7 -9
- package/tools/figma/figma-api/{get-file-version-history.js → get-file-version-history.ts} +7 -9
- package/tools/figma/figma-api/{get-file.js → get-file.ts} +7 -9
- package/tools/figma/figma-api/{get-image-fills.js → get-image-fills.ts} +7 -9
- package/tools/figma/figma-api/{get-library-action-analytics.js → get-library-action-analytics.ts} +7 -9
- package/tools/figma/figma-api/{get-library-usage-analytics.js → get-library-usage-analytics.ts} +7 -9
- package/tools/figma/figma-api/{list-comments-on-a-file.js → list-comments-on-a-file.ts} +8 -10
- package/tools/figma/figma-api/{list-component-sets-in-a-file.js → list-component-sets-in-a-file.ts} +7 -9
- package/tools/figma/figma-api/{list-components-in-a-file.js → list-components-in-a-file.ts} +7 -9
- package/tools/figma/figma-api/{list-dev-resources-for-a-file.js → list-dev-resources-for-a-file.ts} +7 -9
- package/tools/figma/figma-api/{list-files-in-a-project.js → list-files-in-a-project.ts} +7 -9
- package/tools/figma/figma-api/{list-projects-in-a-team.js → list-projects-in-a-team.ts} +7 -9
- package/tools/figma/figma-api/{list-published-libraries.js → list-published-libraries.ts} +6 -8
- package/tools/figma/figma-api/{list-styles-in-a-file.js → list-styles-in-a-file.ts} +7 -9
- package/tools/figma/figma-api/{list-variables-for-a-file.js → list-variables-for-a-file.ts} +7 -9
- package/tools/figma/figma-api/{post-a-comment-to-a-file.js → post-a-comment-to-a-file.ts} +7 -9
- package/tools/paths.ts +25 -0
- package/tsconfig.json +28 -0
- package/commands/tools.js +0 -65
- package/lib/tools.js +0 -12
- package/mcpServer.js +0 -170
- package/tools/paths.js +0 -25
package/LICENSE
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
4
|
-
Copyright (c) 2025 Method Black Studio
|
|
3
|
+
Copyright (c) 2026 Abhimanyu Rana @planetabhi
|
|
5
4
|
|
|
6
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Figma MCP Server
|
|
2
|
-
A
|
|
2
|
+
A comprehensive local MCP server for Figma. Connect Figma with the Gemini CLI, Cursor, and Claude Desktop.
|
|
3
|
+
|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
### Prerequisites
|
|
7
|
+
|
|
8
|
+
- [Bun](https://bun.sh/) (>= 1.1.0)
|
|
3
9
|
|
|
4
10
|
## Install
|
|
5
11
|
Install the server
|
|
@@ -24,21 +30,22 @@ List descriptions and parameters from all available tools
|
|
|
24
30
|
|
|
25
31
|
```bash
|
|
26
32
|
bun list-tools
|
|
33
|
+
# or
|
|
34
|
+
bun index.ts tools
|
|
27
35
|
```
|
|
28
36
|
|
|
29
37
|
## Run the MCP Server
|
|
30
38
|
|
|
31
|
-
### Find
|
|
39
|
+
### Find bun and server path
|
|
32
40
|
|
|
33
41
|
```bash
|
|
34
|
-
# Find
|
|
35
|
-
which
|
|
42
|
+
# Find bun path
|
|
43
|
+
which bun
|
|
36
44
|
|
|
37
45
|
# Get the absolute path of the MCP server
|
|
38
|
-
realpath mcpServer.
|
|
46
|
+
realpath mcpServer.ts
|
|
39
47
|
```
|
|
40
48
|
|
|
41
|
-
|
|
42
49
|
### Run with Claude Desktop
|
|
43
50
|
|
|
44
51
|
1. Open Claude Desktop → **Settings** → **Developers** → **Edit Config** and add your server:
|
|
@@ -47,8 +54,8 @@ realpath mcpServer.js
|
|
|
47
54
|
{
|
|
48
55
|
"mcpServers": {
|
|
49
56
|
"figma-mcp-server": {
|
|
50
|
-
"command": "<
|
|
51
|
-
"args": ["<absolute_path_to_mcpServer.
|
|
57
|
+
"command": "<absolute_path_to_bun>",
|
|
58
|
+
"args": ["<absolute_path_to_mcpServer.ts>"]
|
|
52
59
|
}
|
|
53
60
|
}
|
|
54
61
|
}
|
|
@@ -73,8 +80,8 @@ mkdir -p ~/.gemini
|
|
|
73
80
|
echo '{
|
|
74
81
|
"mcpServers": {
|
|
75
82
|
"figma-mcp-server": {
|
|
76
|
-
"command": "<
|
|
77
|
-
"args": ["mcpServer.
|
|
83
|
+
"command": "<absolute_path_to_bun>",
|
|
84
|
+
"args": ["mcpServer.ts"],
|
|
78
85
|
"cwd": "<absolute_path_to_working_directory>",
|
|
79
86
|
"env": {
|
|
80
87
|
"FIGMA_API_KEY": "your_figma_api_key_here"
|
|
@@ -97,7 +104,26 @@ npx https://github.com/google-gemini/gemini-cli
|
|
|
97
104
|
- Use `/mcp schema` to show tool parameter schemas
|
|
98
105
|
- Use `/mcp nodesc` to hide descriptions
|
|
99
106
|
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
### Troubleshooting
|
|
110
|
+
|
|
111
|
+
- Missing Figma token
|
|
112
|
+
- Error: missing or invalid `FIGMA_API_KEY`.
|
|
113
|
+
- Ensure `.env` exists next to `mcpServer.ts` with `FIGMA_API_KEY=...`.
|
|
114
|
+
- Port already in use (SSE mode)
|
|
115
|
+
- Run SSE on a custom port: `PORT=3005 bun mcpServer.ts --sse`.
|
|
116
|
+
- Bun not found
|
|
117
|
+
- Ensure `which bun` returns a path.
|
|
118
|
+
- Restart your shell after installing Bun.
|
|
119
|
+
- Using npm instead of Bun
|
|
120
|
+
- Replace `bun i` → `npm i`
|
|
121
|
+
- Replace `bun list-tools` → `npx tsx index.ts tools`
|
|
122
|
+
- Manual start not required
|
|
123
|
+
- Only start manually for SSE or local web endpoint: `bun mcpServer.ts --sse`
|
|
124
|
+
- Default port is `3001`, override with `PORT=<port>`
|
|
125
|
+
|
|
100
126
|
|
|
101
127
|
---
|
|
102
128
|
|
|
103
|
-
⋛⋋( ⊙◊⊙)⋌⋚
|
|
129
|
+
[MIT License](https://raw.githubusercontent.com/planetabhi/figma-mcp-server/refs/heads/main/LICENSE) · By [@planetabhi](https://planetabhi.com/) ⋛⋋( ⊙◊⊙)⋌⋚
|
package/bun.lock
CHANGED
|
@@ -4,21 +4,59 @@
|
|
|
4
4
|
"": {
|
|
5
5
|
"name": "figma-mcp-server",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
7
|
+
"@clack/prompts": "^0.11.0",
|
|
8
|
+
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
9
|
+
"commander": "^14.0.2",
|
|
10
|
+
"dotenv": "^17.2.3",
|
|
11
|
+
"express": "^5.2.1",
|
|
12
|
+
"picocolors": "^1.1.1",
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/express": "^5.0.6",
|
|
16
|
+
"@types/node": "^25.0.3",
|
|
17
|
+
"bun-types": "^1.3.5",
|
|
18
|
+
"typescript": "^5.9.3",
|
|
11
19
|
},
|
|
12
20
|
},
|
|
13
21
|
},
|
|
14
22
|
"packages": {
|
|
15
|
-
"@
|
|
23
|
+
"@clack/core": ["@clack/core@0.5.0", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow=="],
|
|
24
|
+
|
|
25
|
+
"@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="],
|
|
26
|
+
|
|
27
|
+
"@hono/node-server": ["@hono/node-server@1.19.7", "", { "peerDependencies": { "hono": "^4" } }, "sha512-vUcD0uauS7EU2caukW8z5lJKtoGMokxNbJtBiwHgpqxEXokaHCBkQUmCHhjFB1VUTWdqj25QoMkMKzgjq+uhrw=="],
|
|
28
|
+
|
|
29
|
+
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.25.1", "", { "dependencies": { "@hono/node-server": "^1.19.7", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "jose": "^6.1.1", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.0" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-yO28oVFFC7EBoiKdAn+VqRm+plcfv4v0xp6osG/VsCB0NlPZWi87ajbCZZ8f/RvOFLEu7//rSRmuZZ7lMoe3gQ=="],
|
|
30
|
+
|
|
31
|
+
"@types/body-parser": ["@types/body-parser@1.19.6", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g=="],
|
|
32
|
+
|
|
33
|
+
"@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="],
|
|
34
|
+
|
|
35
|
+
"@types/express": ["@types/express@5.0.6", "", { "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^5.0.0", "@types/serve-static": "^2" } }, "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA=="],
|
|
36
|
+
|
|
37
|
+
"@types/express-serve-static-core": ["@types/express-serve-static-core@5.1.0", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-jnHMsrd0Mwa9Cf4IdOzbz543y4XJepXrbia2T4b6+spXC2We3t1y6K44D3mR8XMFSXMCf3/l7rCgddfx7UNVBA=="],
|
|
38
|
+
|
|
39
|
+
"@types/http-errors": ["@types/http-errors@2.0.5", "", {}, "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg=="],
|
|
40
|
+
|
|
41
|
+
"@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
|
42
|
+
|
|
43
|
+
"@types/qs": ["@types/qs@6.14.0", "", {}, "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ=="],
|
|
44
|
+
|
|
45
|
+
"@types/range-parser": ["@types/range-parser@1.2.7", "", {}, "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="],
|
|
46
|
+
|
|
47
|
+
"@types/send": ["@types/send@1.2.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ=="],
|
|
48
|
+
|
|
49
|
+
"@types/serve-static": ["@types/serve-static@2.2.0", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*" } }, "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ=="],
|
|
16
50
|
|
|
17
51
|
"accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
|
18
52
|
|
|
19
|
-
"ajv": ["ajv@
|
|
53
|
+
"ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
|
|
20
54
|
|
|
21
|
-
"
|
|
55
|
+
"ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],
|
|
56
|
+
|
|
57
|
+
"body-parser": ["body-parser@2.2.1", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.0", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw=="],
|
|
58
|
+
|
|
59
|
+
"bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="],
|
|
22
60
|
|
|
23
61
|
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
|
24
62
|
|
|
@@ -26,9 +64,9 @@
|
|
|
26
64
|
|
|
27
65
|
"call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
|
|
28
66
|
|
|
29
|
-
"commander": ["commander@14.0.
|
|
67
|
+
"commander": ["commander@14.0.2", "", {}, "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ=="],
|
|
30
68
|
|
|
31
|
-
"content-disposition": ["content-disposition@1.0.
|
|
69
|
+
"content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="],
|
|
32
70
|
|
|
33
71
|
"content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="],
|
|
34
72
|
|
|
@@ -40,11 +78,11 @@
|
|
|
40
78
|
|
|
41
79
|
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
|
42
80
|
|
|
43
|
-
"debug": ["debug@4.4.
|
|
81
|
+
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
|
44
82
|
|
|
45
83
|
"depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
|
|
46
84
|
|
|
47
|
-
"dotenv": ["dotenv@
|
|
85
|
+
"dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="],
|
|
48
86
|
|
|
49
87
|
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
|
50
88
|
|
|
@@ -64,17 +102,17 @@
|
|
|
64
102
|
|
|
65
103
|
"eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],
|
|
66
104
|
|
|
67
|
-
"eventsource-parser": ["eventsource-parser@3.0.
|
|
105
|
+
"eventsource-parser": ["eventsource-parser@3.0.6", "", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="],
|
|
68
106
|
|
|
69
|
-
"express": ["express@5.1
|
|
107
|
+
"express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="],
|
|
70
108
|
|
|
71
109
|
"express-rate-limit": ["express-rate-limit@7.5.1", "", { "peerDependencies": { "express": ">= 4.11" } }, "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw=="],
|
|
72
110
|
|
|
73
111
|
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
|
74
112
|
|
|
75
|
-
"fast-
|
|
113
|
+
"fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="],
|
|
76
114
|
|
|
77
|
-
"finalhandler": ["finalhandler@2.1.
|
|
115
|
+
"finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="],
|
|
78
116
|
|
|
79
117
|
"forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
|
|
80
118
|
|
|
@@ -92,9 +130,11 @@
|
|
|
92
130
|
|
|
93
131
|
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
|
94
132
|
|
|
95
|
-
"
|
|
133
|
+
"hono": ["hono@4.11.3", "", {}, "sha512-PmQi306+M/ct/m5s66Hrg+adPnkD5jiO6IjA7WhWw0gSBSo1EcRegwuI1deZ+wd5pzCGynCcn2DprnE4/yEV4w=="],
|
|
96
134
|
|
|
97
|
-
"
|
|
135
|
+
"http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
|
|
136
|
+
|
|
137
|
+
"iconv-lite": ["iconv-lite@0.7.1", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw=="],
|
|
98
138
|
|
|
99
139
|
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
|
100
140
|
|
|
@@ -104,7 +144,11 @@
|
|
|
104
144
|
|
|
105
145
|
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
|
106
146
|
|
|
107
|
-
"
|
|
147
|
+
"jose": ["jose@6.1.3", "", {}, "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="],
|
|
148
|
+
|
|
149
|
+
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
|
150
|
+
|
|
151
|
+
"json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="],
|
|
108
152
|
|
|
109
153
|
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
|
110
154
|
|
|
@@ -114,7 +158,7 @@
|
|
|
114
158
|
|
|
115
159
|
"mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
|
|
116
160
|
|
|
117
|
-
"mime-types": ["mime-types@3.0.
|
|
161
|
+
"mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
|
118
162
|
|
|
119
163
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
|
120
164
|
|
|
@@ -132,29 +176,29 @@
|
|
|
132
176
|
|
|
133
177
|
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
|
134
178
|
|
|
135
|
-
"path-to-regexp": ["path-to-regexp@8.
|
|
179
|
+
"path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="],
|
|
136
180
|
|
|
137
|
-
"
|
|
181
|
+
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
|
138
182
|
|
|
139
|
-
"
|
|
183
|
+
"pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="],
|
|
140
184
|
|
|
141
|
-
"
|
|
185
|
+
"proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
|
|
142
186
|
|
|
143
187
|
"qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="],
|
|
144
188
|
|
|
145
189
|
"range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
|
|
146
190
|
|
|
147
|
-
"raw-body": ["raw-body@3.0.
|
|
191
|
+
"raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="],
|
|
148
192
|
|
|
149
|
-
"
|
|
193
|
+
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
|
|
150
194
|
|
|
151
|
-
"
|
|
195
|
+
"router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="],
|
|
152
196
|
|
|
153
197
|
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
|
154
198
|
|
|
155
|
-
"send": ["send@1.2.
|
|
199
|
+
"send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="],
|
|
156
200
|
|
|
157
|
-
"serve-static": ["serve-static@2.2.
|
|
201
|
+
"serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="],
|
|
158
202
|
|
|
159
203
|
"setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
|
|
160
204
|
|
|
@@ -170,15 +214,19 @@
|
|
|
170
214
|
|
|
171
215
|
"side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
|
|
172
216
|
|
|
217
|
+
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
|
218
|
+
|
|
173
219
|
"statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
|
|
174
220
|
|
|
175
221
|
"toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
|
|
176
222
|
|
|
177
223
|
"type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
|
|
178
224
|
|
|
179
|
-
"
|
|
225
|
+
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
180
226
|
|
|
181
|
-
"
|
|
227
|
+
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
|
228
|
+
|
|
229
|
+
"unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
|
|
182
230
|
|
|
183
231
|
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
|
|
184
232
|
|
|
@@ -186,10 +234,8 @@
|
|
|
186
234
|
|
|
187
235
|
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
|
188
236
|
|
|
189
|
-
"zod": ["zod@
|
|
190
|
-
|
|
191
|
-
"zod-to-json-schema": ["zod-to-json-schema@3.24.6", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg=="],
|
|
237
|
+
"zod": ["zod@4.2.1", "", {}, "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw=="],
|
|
192
238
|
|
|
193
|
-
"
|
|
239
|
+
"zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],
|
|
194
240
|
}
|
|
195
241
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { intro, outro, spinner, select, isCancel, note, log } from "@clack/prompts";
|
|
3
|
+
import pc from "picocolors";
|
|
4
|
+
import { discoverTools, type ToolWithDefinition } from "../lib/tools.ts";
|
|
5
|
+
|
|
6
|
+
export function registerToolsCommand(program: Command) {
|
|
7
|
+
program
|
|
8
|
+
.command("tools")
|
|
9
|
+
.description("Explore available API tools")
|
|
10
|
+
.action(async () => {
|
|
11
|
+
console.clear();
|
|
12
|
+
intro(pc.bgCyan(pc.black(" Figma MCP Server ")));
|
|
13
|
+
|
|
14
|
+
const s = spinner();
|
|
15
|
+
s.start("Discovering tools...");
|
|
16
|
+
const tools = await discoverTools();
|
|
17
|
+
s.stop(`Found ${tools.length} tools`);
|
|
18
|
+
|
|
19
|
+
if (tools.length === 0) {
|
|
20
|
+
note("No tools found.", "Info");
|
|
21
|
+
outro("Done");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
while (true) {
|
|
26
|
+
const options: { value: ToolWithDefinition | string; label: string; hint?: string }[] = tools.map((t) => ({
|
|
27
|
+
value: t,
|
|
28
|
+
label: t.definition.function.name,
|
|
29
|
+
hint: t.definition.function.description?.slice(0, 50) + (t.definition.function.description && t.definition.function.description.length > 50 ? "..." : "")
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
const selectedTool = await select({
|
|
33
|
+
message: "Select a tool to view details (Expand)",
|
|
34
|
+
options: [{ value: 'all', label: pc.cyan('Expand All') }, ...options, { value: 'exit', label: pc.red('Exit') }] as any,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
if (isCancel(selectedTool) || selectedTool === 'exit') {
|
|
38
|
+
outro("Exited tool explorer");
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (selectedTool === 'all') {
|
|
43
|
+
console.clear();
|
|
44
|
+
log.info(pc.magenta(pc.bold("All Tools Details")));
|
|
45
|
+
|
|
46
|
+
tools.forEach(tool => {
|
|
47
|
+
const def = tool.definition.function;
|
|
48
|
+
console.log(pc.green(pc.bold(`\nTool: ${def.name}`)));
|
|
49
|
+
console.log(pc.white(`Description: ${def.description || "No description"}`));
|
|
50
|
+
|
|
51
|
+
if (def.parameters?.properties && Object.keys(def.parameters.properties).length > 0) {
|
|
52
|
+
console.log(pc.yellow("Parameters:"));
|
|
53
|
+
Object.entries(def.parameters.properties).forEach(([name, details]) => {
|
|
54
|
+
console.log(` ${pc.cyan(name)}: ${pc.dim(details.description || "No description")}`);
|
|
55
|
+
});
|
|
56
|
+
} else {
|
|
57
|
+
console.log(pc.dim("No parameters required."));
|
|
58
|
+
}
|
|
59
|
+
console.log(pc.dim("\n────────────────────────────────────────"));
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
outro("Done");
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const tool = selectedTool as ToolWithDefinition;
|
|
67
|
+
const def = tool.definition.function;
|
|
68
|
+
|
|
69
|
+
console.clear();
|
|
70
|
+
log.info(pc.magenta(pc.bold(`Tool: ${def.name}`)));
|
|
71
|
+
log.message(pc.white(def.description || "No description"));
|
|
72
|
+
|
|
73
|
+
if (def.parameters?.properties && Object.keys(def.parameters.properties).length > 0) {
|
|
74
|
+
log.info(pc.yellow("Parameters:"));
|
|
75
|
+
Object.entries(def.parameters.properties).forEach(([name, details]) => {
|
|
76
|
+
console.log(` ${pc.cyan(name)}: ${pc.dim(details.description || "No description")}`);
|
|
77
|
+
});
|
|
78
|
+
} else {
|
|
79
|
+
log.info(pc.dim("No parameters required."));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
console.log(pc.dim("\n────────────────────────────────────────\n"));
|
|
83
|
+
|
|
84
|
+
// Continue loop implicitly acts as "collapse"/"back"
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
package/{index.js → index.ts}
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
import { registerToolsCommand } from "./commands/tools.
|
|
2
|
+
import { registerToolsCommand } from "./commands/tools.ts";
|
|
3
3
|
|
|
4
4
|
const program = new Command();
|
|
5
5
|
|
|
6
6
|
registerToolsCommand(program);
|
|
7
7
|
|
|
8
|
-
program.parse(process.argv);
|
|
8
|
+
program.parse(process.argv);
|
package/lib/tools.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { toolPaths } from "../tools/paths.ts";
|
|
2
|
+
|
|
3
|
+
export interface ApiTool {
|
|
4
|
+
definition: {
|
|
5
|
+
type: 'function';
|
|
6
|
+
function: {
|
|
7
|
+
name: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
parameters?: {
|
|
10
|
+
type: string;
|
|
11
|
+
properties: Record<string, any>;
|
|
12
|
+
required?: string[];
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
function: (args: any) => Promise<any>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type ToolWithDefinition = ApiTool & { path: string };
|
|
20
|
+
|
|
21
|
+
export async function discoverTools(): Promise<ToolWithDefinition[]> {
|
|
22
|
+
const toolPromises = toolPaths.map(async (file) => {
|
|
23
|
+
const module = await import(`../tools/${file}`);
|
|
24
|
+
return {
|
|
25
|
+
...module.apiTool,
|
|
26
|
+
path: file,
|
|
27
|
+
} as ToolWithDefinition;
|
|
28
|
+
});
|
|
29
|
+
return Promise.all(toolPromises);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getFigmaToken(): string {
|
|
33
|
+
const token = process.env.FIGMA_API_KEY;
|
|
34
|
+
if (!token) {
|
|
35
|
+
throw new Error("FIGMA_API_KEY environment variable is not set.");
|
|
36
|
+
}
|
|
37
|
+
return token;
|
|
38
|
+
}
|