figma-mcp-server 0.0.0-alpha.1 → 0.1.0-beta.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/Dockerfile +9 -0
- package/LICENSE +19 -0
- package/README.md +22 -80
- package/commands/tools.js +65 -0
- package/lib/tools.js +16 -0
- package/mcpServer.js +145 -0
- package/package.json +9 -4
- package/tools/figma/figma-api/add-webhook.js +57 -0
- package/tools/figma/figma-api/create-variable-collection.js +84 -0
- package/tools/figma/figma-api/delete-webhook.js +64 -0
- package/tools/figma/figma-api/get-actions-analytics.js +67 -0
- package/tools/figma/figma-api/get-all-webhooks-for-team.js +56 -0
- package/tools/figma/figma-api/get-design-node.js +72 -0
- package/tools/figma/figma-api/get-design.js +66 -0
- package/tools/figma/figma-api/get-dev-resources.js +67 -0
- package/tools/figma/figma-api/get-file-comments.js +67 -0
- package/tools/figma/figma-api/get-image-node.js +74 -0
- package/tools/figma/figma-api/get-images.js +66 -0
- package/tools/figma/figma-api/get-library-analytics.js +66 -0
- package/tools/figma/figma-api/get-project-files.js +66 -0
- package/tools/figma/figma-api/get-team-projects.js +66 -0
- package/tools/figma/figma-api/post-a-new-comment.js +89 -0
- package/tools/figma/figma-api/post-dev-resource.js +93 -0
- package/tools/figma/figma-api/reply-to-comment.js +84 -0
- package/tools/paths.js +19 -0
package/Dockerfile
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Abhimanyu Rana @planetabhi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, and/or publish copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,69 +1,42 @@
|
|
|
1
1
|
# Figma MCP Server
|
|
2
|
+
MCP server for Figma
|
|
2
3
|
|
|
3
|
-
###
|
|
4
|
-
|
|
5
|
-
**1. Install dependencies**
|
|
6
|
-
|
|
7
|
-
Run from your project's root directory:
|
|
8
|
-
|
|
9
|
-
```sh
|
|
10
|
-
npm install
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
### 🔐 Set tool environment variables
|
|
14
|
-
|
|
15
|
-
In the `.env` file, you'll see environment variable placeholders, one for each workspace that the selected tools are from. For example, if you selected requests from 2 workspaces, e.g. Acme and Widgets, you'll see two placeholders:
|
|
4
|
+
### Set tool environment variables
|
|
5
|
+
In the `.env` file, set the `FIGMA_API_KEY` to your Figma API key.
|
|
16
6
|
|
|
17
7
|
```
|
|
18
|
-
|
|
19
|
-
WIDGETS_API_KEY=
|
|
8
|
+
FIGMA_API_KEY=
|
|
20
9
|
```
|
|
21
10
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
```javascript
|
|
25
|
-
// environment variables are used inside of each tool file
|
|
26
|
-
const apiKey = process.env.ACME_API_KEY;
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
**Caveat:** This may not be correct for every API. The generation logic is relatively simple - for each workspace, we create an environment variable with the same name as the workspace slug, and then use that environment variable in each tool file that belongs to that workspace. If this isn't the right behavior for your chosen API, no problem! You can manually update anything in the `.env` file or tool files to accurately reflect the API's method of authentication.
|
|
30
|
-
|
|
31
|
-
### 🛠️ List Available Tools
|
|
32
|
-
|
|
33
|
-
List descriptions and parameters from all generated tools with:
|
|
11
|
+
### Install
|
|
12
|
+
Install the server
|
|
34
13
|
|
|
35
14
|
```sh
|
|
36
|
-
|
|
15
|
+
git clone https://github.com/planetabhi/figma-mcp-server.git
|
|
16
|
+
cd figma-mcp-server
|
|
17
|
+
pnpm i
|
|
37
18
|
```
|
|
38
19
|
|
|
39
|
-
|
|
20
|
+
### List Figma Tools
|
|
21
|
+
List descriptions and parameters from all available Figma tools
|
|
40
22
|
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
Workspace: acme-workspace
|
|
45
|
-
Collection: useful-api
|
|
46
|
-
list_all_customers
|
|
47
|
-
Description: Retrieve a list of useful things.
|
|
48
|
-
Parameters:
|
|
49
|
-
- magic: The required magic power
|
|
50
|
-
- limit: Number of results returned
|
|
51
|
-
[...additional parameters...]
|
|
23
|
+
```sh
|
|
24
|
+
pnpm list-tools
|
|
52
25
|
```
|
|
53
26
|
|
|
54
|
-
##
|
|
27
|
+
## Run the MCP Server
|
|
55
28
|
|
|
56
|
-
The MCP Server (`mcpServer.js`) exposes your
|
|
29
|
+
The MCP Server (`mcpServer.js`) exposes your Figma API tools to MCP-compatible clients.
|
|
57
30
|
|
|
58
|
-
###
|
|
31
|
+
### Run with Postman
|
|
59
32
|
|
|
60
|
-
|
|
33
|
+
Postman desktop app is the easiest way to run and test MCP servers.
|
|
61
34
|
|
|
62
|
-
Step 1: Download the latest Postman
|
|
35
|
+
Step 1: Download the latest Postman app from [https://www.postman.com/downloads/](https://www.postman.com/downloads/).
|
|
63
36
|
|
|
64
37
|
Step 2: Read out the documentation article [here](https://learning.postman.com/docs/postman-ai-agent-builder/mcp-requests/overview/) for the next steps.
|
|
65
38
|
|
|
66
|
-
###
|
|
39
|
+
### Run with Claude Desktop
|
|
67
40
|
|
|
68
41
|
To integrate with Claude Desktop:
|
|
69
42
|
|
|
@@ -96,7 +69,7 @@ Restart Claude Desktop to activate this change.
|
|
|
96
69
|
|
|
97
70
|
### Additional Options
|
|
98
71
|
|
|
99
|
-
####
|
|
72
|
+
#### Docker Deployment (Production)
|
|
100
73
|
|
|
101
74
|
For production deployments, you can use Docker:
|
|
102
75
|
|
|
@@ -123,41 +96,10 @@ Add Docker server configuration to Claude Desktop (Settings → Developers → E
|
|
|
123
96
|
|
|
124
97
|
> Add your environment variables (API keys, etc.) inside the `.env` file.
|
|
125
98
|
|
|
126
|
-
####
|
|
99
|
+
#### Server-Sent Events (SSE)
|
|
127
100
|
|
|
128
101
|
To run the server with Server-Sent Events (SSE) support, use the `--sse` flag:
|
|
129
102
|
|
|
130
103
|
```sh
|
|
131
104
|
node mcpServer.js --sse
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## 🐳 Dockerfile (Included)
|
|
135
|
-
|
|
136
|
-
The project comes bundled with the following minimal Docker setup:
|
|
137
|
-
|
|
138
|
-
```dockerfile
|
|
139
|
-
FROM node:22.12-alpine AS builder
|
|
140
|
-
|
|
141
|
-
WORKDIR /app
|
|
142
|
-
COPY package.json package-lock.json ./
|
|
143
|
-
RUN npm install
|
|
144
|
-
|
|
145
|
-
COPY . .
|
|
146
|
-
|
|
147
|
-
ENTRYPOINT ["node", "mcpServer.js"]
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
## ➕ Adding New Tools
|
|
151
|
-
|
|
152
|
-
Extend your agent with more tools easily:
|
|
153
|
-
|
|
154
|
-
1. Visit [Postman Agent Generator](https://postman.com/explore/agent-generator).
|
|
155
|
-
2. Pick new API request(s), generate a new agent, and download it.
|
|
156
|
-
3. Copy new generated tool(s) into your existing project's `tools/` folder.
|
|
157
|
-
4. Update your `tools/paths.js` file to include new tool references.
|
|
158
|
-
|
|
159
|
-
## 💬 Questions & Support
|
|
160
|
-
|
|
161
|
-
Visit the [Postman Agent Generator](https://postman.com/explore/agent-generator) page for updates and new capabilities.
|
|
162
|
-
|
|
163
|
-
Visit the [Postman Community](https://community.postman.com/) to share what you've built, ask questions and get help.
|
|
105
|
+
```
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { discoverTools } from "../lib/tools.js";
|
|
2
|
+
|
|
3
|
+
export function registerToolsCommand(program) {
|
|
4
|
+
program
|
|
5
|
+
.command("tools")
|
|
6
|
+
.description("List all available API tools")
|
|
7
|
+
.action(async () => {
|
|
8
|
+
const tools = await discoverTools();
|
|
9
|
+
if (tools.length === 0) {
|
|
10
|
+
console.log("No tools found. Tools should be organized as:");
|
|
11
|
+
console.log("tools/workspace/collection/request.js\n");
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
console.log("\nAvailable Tools:\n");
|
|
16
|
+
|
|
17
|
+
// Group tools by workspace/collection
|
|
18
|
+
const groupedTools = tools.reduce((acc, tool) => {
|
|
19
|
+
// Extract workspace and collection from path
|
|
20
|
+
const parts = tool.path.split("/");
|
|
21
|
+
const workspace = parts[1] || "Unknown Workspace";
|
|
22
|
+
const collection = parts[2] || "Unknown Collection";
|
|
23
|
+
|
|
24
|
+
if (!acc[workspace]) acc[workspace] = {};
|
|
25
|
+
if (!acc[workspace][collection]) acc[workspace][collection] = [];
|
|
26
|
+
|
|
27
|
+
acc[workspace][collection].push(tool);
|
|
28
|
+
return acc;
|
|
29
|
+
}, {});
|
|
30
|
+
|
|
31
|
+
// Print tools in a hierarchical structure
|
|
32
|
+
for (const [workspace, collections] of Object.entries(groupedTools)) {
|
|
33
|
+
console.log(`Workspace: ${workspace}`);
|
|
34
|
+
for (const [collection, tools] of Object.entries(collections)) {
|
|
35
|
+
console.log(` Collection: ${collection}`);
|
|
36
|
+
tools.forEach(
|
|
37
|
+
({
|
|
38
|
+
definition: {
|
|
39
|
+
function: { name, description, parameters },
|
|
40
|
+
},
|
|
41
|
+
}) => {
|
|
42
|
+
console.log(` ${name}`);
|
|
43
|
+
console.log(
|
|
44
|
+
` Description: ${description || "No description provided"}`
|
|
45
|
+
);
|
|
46
|
+
if (parameters?.properties) {
|
|
47
|
+
console.log(" Parameters:");
|
|
48
|
+
Object.entries(parameters.properties).forEach(
|
|
49
|
+
([name, details]) => {
|
|
50
|
+
console.log(
|
|
51
|
+
` - ${name}: ${
|
|
52
|
+
details.description || "No description"
|
|
53
|
+
}`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
console.log("");
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
console.log("");
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
package/lib/tools.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { toolPaths } from "../tools/paths.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Discovers and loads available tools from the tools directory
|
|
5
|
+
* @returns {Promise<Array>} Array of tool objects
|
|
6
|
+
*/
|
|
7
|
+
export async function discoverTools() {
|
|
8
|
+
const toolPromises = toolPaths.map(async (file) => {
|
|
9
|
+
const module = await import(`../tools/${file}`);
|
|
10
|
+
return {
|
|
11
|
+
...module.apiTool,
|
|
12
|
+
path: file,
|
|
13
|
+
};
|
|
14
|
+
});
|
|
15
|
+
return Promise.all(toolPromises);
|
|
16
|
+
}
|
package/mcpServer.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import dotenv from "dotenv";
|
|
3
|
+
import express from "express";
|
|
4
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
5
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
+
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
7
|
+
import {
|
|
8
|
+
CallToolRequestSchema,
|
|
9
|
+
ErrorCode,
|
|
10
|
+
ListToolsRequestSchema,
|
|
11
|
+
McpError,
|
|
12
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
13
|
+
import { discoverTools } from "./lib/tools.js";
|
|
14
|
+
|
|
15
|
+
import path from "path";
|
|
16
|
+
import { fileURLToPath } from "url";
|
|
17
|
+
|
|
18
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
19
|
+
const __dirname = path.dirname(__filename);
|
|
20
|
+
|
|
21
|
+
dotenv.config({ path: path.resolve(__dirname, ".env") });
|
|
22
|
+
|
|
23
|
+
const SERVER_NAME = "generated-mcp-server";
|
|
24
|
+
|
|
25
|
+
async function transformTools(tools) {
|
|
26
|
+
return tools
|
|
27
|
+
.map((tool) => {
|
|
28
|
+
const definitionFunction = tool.definition?.function;
|
|
29
|
+
if (!definitionFunction) return;
|
|
30
|
+
return {
|
|
31
|
+
name: definitionFunction.name,
|
|
32
|
+
description: definitionFunction.description,
|
|
33
|
+
inputSchema: definitionFunction.parameters,
|
|
34
|
+
};
|
|
35
|
+
})
|
|
36
|
+
.filter(Boolean);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function run() {
|
|
40
|
+
const args = process.argv.slice(2);
|
|
41
|
+
const isSSE = args.includes("--sse");
|
|
42
|
+
|
|
43
|
+
const server = new Server(
|
|
44
|
+
{
|
|
45
|
+
name: SERVER_NAME,
|
|
46
|
+
version: "0.1.0",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
capabilities: {
|
|
50
|
+
tools: {},
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
server.onerror = (error) => console.error("[Error]", error);
|
|
56
|
+
|
|
57
|
+
// Gracefully shutdown on SIGINT
|
|
58
|
+
process.on("SIGINT", async () => {
|
|
59
|
+
await server.close();
|
|
60
|
+
process.exit(0);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const tools = await discoverTools();
|
|
64
|
+
|
|
65
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
66
|
+
tools: await transformTools(tools),
|
|
67
|
+
}));
|
|
68
|
+
|
|
69
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
70
|
+
const toolName = request.params.name;
|
|
71
|
+
const tool = tools.find((t) => t.definition.function.name === toolName);
|
|
72
|
+
|
|
73
|
+
if (!tool) {
|
|
74
|
+
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${toolName}`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const args = request.params.arguments;
|
|
78
|
+
const requiredParameters =
|
|
79
|
+
tool.definition?.function?.parameters?.required || [];
|
|
80
|
+
|
|
81
|
+
for (const requiredParameter of requiredParameters) {
|
|
82
|
+
if (!(requiredParameter in args)) {
|
|
83
|
+
throw new McpError(
|
|
84
|
+
ErrorCode.InvalidParams,
|
|
85
|
+
`Missing required parameter: ${requiredParameter}`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const result = await tool.function(args);
|
|
92
|
+
return {
|
|
93
|
+
content: [
|
|
94
|
+
{
|
|
95
|
+
type: "text",
|
|
96
|
+
text: JSON.stringify(result, null, 2),
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error("[Error] Failed to fetch data:", error);
|
|
102
|
+
throw new McpError(
|
|
103
|
+
ErrorCode.InternalError,
|
|
104
|
+
`API error: ${error.message}`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
if (isSSE) {
|
|
110
|
+
const app = express();
|
|
111
|
+
const transports = {};
|
|
112
|
+
|
|
113
|
+
app.get("/sse", async (_req, res) => {
|
|
114
|
+
const transport = new SSEServerTransport("/messages", res);
|
|
115
|
+
transports[transport.sessionId] = transport;
|
|
116
|
+
|
|
117
|
+
res.on("close", () => {
|
|
118
|
+
delete transports[transport.sessionId];
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
await server.connect(transport);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
app.post("/messages", async (req, res) => {
|
|
125
|
+
const sessionId = req.query.sessionId;
|
|
126
|
+
const transport = transports[sessionId];
|
|
127
|
+
|
|
128
|
+
if (transport) {
|
|
129
|
+
await transport.handlePostMessage(req, res);
|
|
130
|
+
} else {
|
|
131
|
+
res.status(400).send("No transport found for sessionId");
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const port = process.env.PORT || 3001;
|
|
136
|
+
app.listen(port, () => {
|
|
137
|
+
console.log(`[SSE Server] running on port ${port}`);
|
|
138
|
+
});
|
|
139
|
+
} else {
|
|
140
|
+
const transport = new StdioServerTransport();
|
|
141
|
+
await server.connect(transport);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
run().catch(console.error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "figma-mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.0-beta.1",
|
|
4
4
|
"description": "MCP server for Figma",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -24,7 +24,12 @@
|
|
|
24
24
|
],
|
|
25
25
|
"author": "@planetabhi",
|
|
26
26
|
"license": "MIT",
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/planetabhi/figma-mcp-server.git"
|
|
30
|
+
},
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/planetabhi/figma-mcp-server/issues"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/planetabhi/figma-mcp-server#readme"
|
|
30
35
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Function to add a webhook in Figma.
|
|
3
|
+
*
|
|
4
|
+
* @returns {Promise<Object>} - The result of the webhook addition.
|
|
5
|
+
*/
|
|
6
|
+
const executeFunction = async () => {
|
|
7
|
+
const webhookUrl = 'https://api.figma.com/v2/webhooks';
|
|
8
|
+
const token = process.env.FIGMA_API_KEY;
|
|
9
|
+
try {
|
|
10
|
+
// Set up headers for the request
|
|
11
|
+
const headers = {
|
|
12
|
+
'X-Figma-Token': token,
|
|
13
|
+
'Content-Type': 'application/json'
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// Perform the fetch request
|
|
17
|
+
const response = await fetch(webhookUrl, {
|
|
18
|
+
method: 'POST',
|
|
19
|
+
headers
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Check if the response was successful
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
const errorData = await response.json();
|
|
25
|
+
throw new Error(errorData);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Parse and return the response data
|
|
29
|
+
const data = await response.json();
|
|
30
|
+
return data;
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error('Error adding webhook:', error);
|
|
33
|
+
return { error: 'An error occurred while adding the webhook.' };
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Tool configuration for adding a webhook in Figma.
|
|
39
|
+
* @type {Object}
|
|
40
|
+
*/
|
|
41
|
+
const apiTool = {
|
|
42
|
+
function: executeFunction,
|
|
43
|
+
definition: {
|
|
44
|
+
type: 'function',
|
|
45
|
+
function: {
|
|
46
|
+
name: 'add_webhook',
|
|
47
|
+
description: 'Add a webhook in Figma.',
|
|
48
|
+
parameters: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
properties: {},
|
|
51
|
+
required: []
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export { apiTool };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Function to create a variable collection in Figma.
|
|
3
|
+
*
|
|
4
|
+
* @param {Object} args - Arguments for creating the variable collection.
|
|
5
|
+
* @param {string} args.file_key - The key of the Figma file where the variable collection will be created.
|
|
6
|
+
* @param {string} args.name - The name of the new variable collection to be created.
|
|
7
|
+
* @returns {Promise<Object>} - The result of the variable collection creation.
|
|
8
|
+
*/
|
|
9
|
+
const executeFunction = async ({ file_key, name }) => {
|
|
10
|
+
const baseUrl = 'https://api.figma.com/v1';
|
|
11
|
+
const token = process.env.FIGMA_API_KEY;
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
// Construct the URL for the request
|
|
15
|
+
const url = `${baseUrl}/files/${file_key}/variables`;
|
|
16
|
+
|
|
17
|
+
// Set up headers for the request
|
|
18
|
+
const headers = {
|
|
19
|
+
'X-Figma-Token': token,
|
|
20
|
+
'Content-Type': 'application/json'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Create the request body
|
|
24
|
+
const body = JSON.stringify({
|
|
25
|
+
variableCollections: [
|
|
26
|
+
{
|
|
27
|
+
action: 'CREATE',
|
|
28
|
+
name: name
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Perform the fetch request
|
|
34
|
+
const response = await fetch(url, {
|
|
35
|
+
method: 'POST',
|
|
36
|
+
headers,
|
|
37
|
+
body
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Check if the response was successful
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
const errorData = await response.json();
|
|
43
|
+
throw new Error(errorData);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Parse and return the response data
|
|
47
|
+
const data = await response.json();
|
|
48
|
+
return data;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error('Error creating variable collection:', error);
|
|
51
|
+
return { error: 'An error occurred while creating the variable collection.' };
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Tool configuration for creating a variable collection in Figma.
|
|
57
|
+
* @type {Object}
|
|
58
|
+
*/
|
|
59
|
+
const apiTool = {
|
|
60
|
+
function: executeFunction,
|
|
61
|
+
definition: {
|
|
62
|
+
type: 'function',
|
|
63
|
+
function: {
|
|
64
|
+
name: 'create_variable_collection',
|
|
65
|
+
description: 'Create a new variable collection in Figma.',
|
|
66
|
+
parameters: {
|
|
67
|
+
type: 'object',
|
|
68
|
+
properties: {
|
|
69
|
+
file_key: {
|
|
70
|
+
type: 'string',
|
|
71
|
+
description: 'The key of the Figma file where the variable collection will be created.'
|
|
72
|
+
},
|
|
73
|
+
name: {
|
|
74
|
+
type: 'string',
|
|
75
|
+
description: 'The name of the new variable collection to be created.'
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
required: ['file_key', 'name']
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export { apiTool };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Function to delete a specific webhook from Figma.
|
|
3
|
+
*
|
|
4
|
+
* @param {Object} args - Arguments for the deletion.
|
|
5
|
+
* @param {string} args.webhook_id - The ID of the webhook to delete.
|
|
6
|
+
* @returns {Promise<Object>} - The result of the deletion operation.
|
|
7
|
+
*/
|
|
8
|
+
const executeFunction = async ({ webhook_id }) => {
|
|
9
|
+
const baseUrl = 'https://api.figma.com/v1';
|
|
10
|
+
const token = process.env.FIGMA_API_KEY;
|
|
11
|
+
const webhookUrl = `${baseUrl}/webhooks/${webhook_id}`;
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
// Set up headers for the request
|
|
15
|
+
const headers = {
|
|
16
|
+
'X-Figma-Token': token
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Perform the fetch request
|
|
20
|
+
const response = await fetch(webhookUrl, {
|
|
21
|
+
method: 'DELETE',
|
|
22
|
+
headers
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Check if the response was successful
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
const errorData = await response.json();
|
|
28
|
+
throw new Error(errorData);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Return the response data (should be empty for successful deletion)
|
|
32
|
+
return {};
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error('Error deleting webhook:', error);
|
|
35
|
+
return { error: 'An error occurred while deleting the webhook.' };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Tool configuration for deleting a webhook from Figma.
|
|
41
|
+
* @type {Object}
|
|
42
|
+
*/
|
|
43
|
+
const apiTool = {
|
|
44
|
+
function: executeFunction,
|
|
45
|
+
definition: {
|
|
46
|
+
type: 'function',
|
|
47
|
+
function: {
|
|
48
|
+
name: 'delete_webhook',
|
|
49
|
+
description: 'Delete a specific webhook from Figma.',
|
|
50
|
+
parameters: {
|
|
51
|
+
type: 'object',
|
|
52
|
+
properties: {
|
|
53
|
+
webhook_id: {
|
|
54
|
+
type: 'string',
|
|
55
|
+
description: 'The ID of the webhook to delete.'
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
required: ['webhook_id']
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export { apiTool };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Function to get actions analytics for a specific library file in Figma.
|
|
3
|
+
*
|
|
4
|
+
* @param {Object} args - Arguments for the request.
|
|
5
|
+
* @param {string} args.library_file_key - The key of the library file for which to retrieve actions analytics.
|
|
6
|
+
* @returns {Promise<Object>} - The actions analytics related to the library file.
|
|
7
|
+
*/
|
|
8
|
+
const executeFunction = async ({ library_file_key }) => {
|
|
9
|
+
const baseUrl = 'https://api.figma.com/v1';
|
|
10
|
+
const token = process.env.FIGMA_API_KEY;
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
// Construct the URL for the request
|
|
14
|
+
const url = `${baseUrl}/analytics/libraries/${library_file_key}/actions`;
|
|
15
|
+
|
|
16
|
+
// Set up headers for the request
|
|
17
|
+
const headers = {
|
|
18
|
+
'X-Figma-Token': token
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Perform the fetch request
|
|
22
|
+
const response = await fetch(url, {
|
|
23
|
+
method: 'GET',
|
|
24
|
+
headers
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Check if the response was successful
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
const errorData = await response.json();
|
|
30
|
+
throw new Error(errorData);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Parse and return the response data
|
|
34
|
+
const data = await response.json();
|
|
35
|
+
return data;
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error('Error getting actions analytics:', error);
|
|
38
|
+
return { error: 'An error occurred while retrieving actions analytics.' };
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Tool configuration for getting actions analytics for a library file in Figma.
|
|
44
|
+
* @type {Object}
|
|
45
|
+
*/
|
|
46
|
+
const apiTool = {
|
|
47
|
+
function: executeFunction,
|
|
48
|
+
definition: {
|
|
49
|
+
type: 'function',
|
|
50
|
+
function: {
|
|
51
|
+
name: 'get_actions_analytics',
|
|
52
|
+
description: 'Retrieve actions analytics for a specific library file in Figma.',
|
|
53
|
+
parameters: {
|
|
54
|
+
type: 'object',
|
|
55
|
+
properties: {
|
|
56
|
+
library_file_key: {
|
|
57
|
+
type: 'string',
|
|
58
|
+
description: 'The key of the library file for which to retrieve actions analytics.'
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
required: ['library_file_key']
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export { apiTool };
|