figma-mcp-server 0.0.0-alpha.1 → 0.1.0
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 +41 -92
- 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,85 +1,54 @@
|
|
|
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:
|
|
4
|
+
## Install
|
|
5
|
+
Install the server
|
|
8
6
|
|
|
9
7
|
```sh
|
|
10
|
-
|
|
8
|
+
git clone https://github.com/planetabhi/figma-mcp-server.git
|
|
9
|
+
cd figma-mcp-server
|
|
10
|
+
pnpm i
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
###
|
|
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:
|
|
13
|
+
### Set tool environment variables
|
|
14
|
+
In the `.env` file, set the `FIGMA_API_KEY` to your Figma API key.
|
|
16
15
|
|
|
17
16
|
```
|
|
18
|
-
|
|
19
|
-
WIDGETS_API_KEY=
|
|
17
|
+
FIGMA_API_KEY=
|
|
20
18
|
```
|
|
21
19
|
|
|
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:
|
|
20
|
+
### List Figma Tools
|
|
21
|
+
List descriptions and parameters from all available Figma tools
|
|
34
22
|
|
|
35
23
|
```sh
|
|
36
|
-
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
Example:
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
Available Tools:
|
|
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...]
|
|
24
|
+
pnpm list-tools
|
|
52
25
|
```
|
|
53
26
|
|
|
54
|
-
##
|
|
55
|
-
|
|
56
|
-
The MCP Server (`mcpServer.js`) exposes your automated API tools to MCP-compatible clients, such as Claude Desktop or the Postman Desktop Application.
|
|
57
|
-
|
|
58
|
-
### A) 🖥️ Run with Postman
|
|
27
|
+
## Run the MCP Server
|
|
59
28
|
|
|
60
|
-
|
|
29
|
+
MCP Server `mcpServer.js` exposes your Figma API tools to MCP-compatible clients.
|
|
61
30
|
|
|
62
|
-
|
|
31
|
+
1. Find node path: `which node`
|
|
32
|
+
2. Find mcpServer.js path: `realpath mcpServer.js`
|
|
63
33
|
|
|
64
|
-
|
|
34
|
+
### Run with Postman
|
|
65
35
|
|
|
66
|
-
|
|
36
|
+
Postman desktop app is the easiest way to [run and test MCP servers](https://learning.postman.com/docs/postman-ai-agent-builder/mcp-requests/overview/).
|
|
67
37
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
38
|
+
1. Choose an existing workspace or create a new one.
|
|
39
|
+
2. Select New > MCP icon MCP. Postman opens a new MCP request in a new tab.
|
|
40
|
+
3. Select the server's communication method STDIO.
|
|
41
|
+
4. Enter the server's command and arguments.
|
|
71
42
|
|
|
72
43
|
```sh
|
|
73
|
-
|
|
44
|
+
STDIO <absolute_path_to_node> <absolute_path_to_mcpServer.js>
|
|
74
45
|
```
|
|
75
46
|
|
|
76
|
-
|
|
47
|
+
Or you can fork Postman [collection here](https://www.postman.com/doitagain/workspace/figma/collection/68369062465421c338809955?action=share&creator=17652550).
|
|
77
48
|
|
|
78
|
-
|
|
79
|
-
realpath mcpServer.js
|
|
80
|
-
```
|
|
49
|
+
### Run with Claude Desktop
|
|
81
50
|
|
|
82
|
-
|
|
51
|
+
1. Open Claude Desktop → **Settings** → **Developers** → **Edit Config** and add your server:
|
|
83
52
|
|
|
84
53
|
```json
|
|
85
54
|
{
|
|
@@ -92,11 +61,22 @@ realpath mcpServer.js
|
|
|
92
61
|
}
|
|
93
62
|
```
|
|
94
63
|
|
|
95
|
-
Restart Claude Desktop to activate this change.
|
|
64
|
+
2. Restart Claude Desktop to activate this change.
|
|
65
|
+
|
|
66
|
+
#### Try it out:
|
|
67
|
+
|
|
68
|
+
1. Open Claude Desktop, then click on the search and tools icon button and select your server name from the list.
|
|
69
|
+
2. Enable the `get_design_node` tool from the tools list.
|
|
70
|
+
3. Copy a design node link from a Figma file, then paste it in Claude Desktop.
|
|
71
|
+
4. It will return the design node data and other information.
|
|
72
|
+
|
|
73
|
+
> Note: Some tools may be non-functional at the moment because of changes to the Figma API. Working on updating the endpoints in future updates.
|
|
74
|
+
|
|
75
|
+
---
|
|
96
76
|
|
|
97
77
|
### Additional Options
|
|
98
78
|
|
|
99
|
-
####
|
|
79
|
+
#### Docker Deployment (Production)
|
|
100
80
|
|
|
101
81
|
For production deployments, you can use Docker:
|
|
102
82
|
|
|
@@ -123,41 +103,10 @@ Add Docker server configuration to Claude Desktop (Settings → Developers → E
|
|
|
123
103
|
|
|
124
104
|
> Add your environment variables (API keys, etc.) inside the `.env` file.
|
|
125
105
|
|
|
126
|
-
####
|
|
106
|
+
#### Server-Sent Events (SSE)
|
|
127
107
|
|
|
128
108
|
To run the server with Server-Sent Events (SSE) support, use the `--sse` flag:
|
|
129
109
|
|
|
130
110
|
```sh
|
|
131
111
|
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.
|
|
112
|
+
```
|
|
@@ -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",
|
|
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 };
|