import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { sendCommandToFigma } from "../communication";
import { logger } from "../logger";
/**
* Register styling-related MCP tools
*/
export function registerStylingTools(server: McpServer): void {
// Set Fill Color
server.tool(
"set_fill_color",
"Set the fill color of a node in Figma (TextNode, FrameNode, etc.)",
{
nodeId: z.string().describe("The ID of the node to modify"),
r: z.number().min(0).max(1).describe("Red component (0-1)"),
g: z.number().min(0).max(1).describe("Green component (0-1)"),
b: z.number().min(0).max(1).describe("Blue component (0-1)"),
a: z.number().min(0).max(1).optional().describe("Alpha component (0-1)"),
},
async ({ nodeId, r, g, b, a }) => {
try {
const result = await sendCommandToFigma<{ name: string }>(
"set_fill_color",
{
nodeId,
color: { r, g, b, a: a ?? 1 },
},
);
return {
content: [
{
type: "text",
text: `Set fill color of node "${result.name}" to RGBA(${r}, ${g}, ${b}, ${a ?? 1})`,
},
],
};
} catch (error) {
logger.error("Error setting fill color", error);
return {
content: [
{
type: "text",
text: `Error setting fill color: ${
error instanceof Error ? error.message : String(error)
}`,
},
],
};
}
},
);
// Set Stroke Color
server.tool(
"set_stroke_color",
"Set the stroke color and weight of a node in Figma",
{
nodeId: z.string().describe("The ID of the node to modify"),
r: z.number().min(0).max(1).describe("Red component (0-1)"),
g: z.number().min(0).max(1).describe("Green component (0-1)"),
b: z.number().min(0).max(1).describe("Blue component (0-1)"),
a: z.number().min(0).max(1).optional().describe("Alpha component (0-1)"),
weight: z.number().positive().optional().describe("Stroke weight"),
},
async ({ nodeId, r, g, b, a, weight }) => {
try {
const result = await sendCommandToFigma<{ name: string }>(
"set_stroke_color",
{
nodeId,
color: { r, g, b, a: a ?? 1 },
weight: weight ?? 1,
},
);
return {
content: [
{
type: "text",
text: `Set stroke color of node "${result.name}" to RGBA(${r}, ${g}, ${b}, ${a ?? 1}) with weight ${weight ?? 1}`,
},
],
};
} catch (error) {
logger.error("Error setting stroke color", error);
return {
content: [
{
type: "text",
text: `Error setting stroke color: ${
error instanceof Error ? error.message : String(error)
}`,
},
],
};
}
},
);
// Set Corner Radius
server.tool(
"set_corner_radius",
"Set the corner radius of a node in Figma",
{
nodeId: z.string().describe("The ID of the node to modify"),
radius: z.number().min(0).describe("Corner radius value"),
corners: z
.tuple([z.boolean(), z.boolean(), z.boolean(), z.boolean()])
.optional()
.describe(
"Which corners to apply radius to [topLeft, topRight, bottomRight, bottomLeft]",
),
},
async ({ nodeId, radius, corners }) => {
try {
const result = await sendCommandToFigma<{ name: string }>(
"set_corner_radius",
{ nodeId, radius, corners },
);
return {
content: [
{
type: "text",
text: `Set corner radius of node "${result.name}" to ${radius}`,
},
],
};
} catch (error) {
logger.error("Error setting corner radius", error);
return {
content: [
{
type: "text",
text: `Error setting corner radius: ${
error instanceof Error ? error.message : String(error)
}`,
},
],
};
}
},
);
}