create_element
Generate and customize Excalidraw elements like rectangles, arrows, text, and more by defining type, position, size, colors, and styles via structured API input parameters.
Instructions
Create a new Excalidraw element
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| backgroundColor | No | ||
| fontFamily | No | ||
| fontSize | No | ||
| height | No | ||
| opacity | No | ||
| roughness | No | ||
| strokeColor | No | ||
| strokeWidth | No | ||
| text | No | ||
| type | Yes | ||
| width | No | ||
| x | Yes | ||
| y | Yes |
Implementation Reference
- src/index.js:293-365 (handler)Handler logic for the 'create_element' tool. Validates input parameters using ElementSchema, generates a unique ID and default properties for the Excalidraw element, handles special cases for arrows/lines, stores the element in the in-memory 'elements' Map, and returns a confirmation with the new element's ID and type.case 'create_element': { if (args.fontFamily && typeof args.fontFamily === 'string') { const fontMap = { "virgil": 1, "helvetica": 2, "cascadia": 3 }; args.fontFamily = fontMap[args.fontFamily.toLowerCase()] ?? 1; } const params = ElementSchema.passthrough().parse(args); const id = generateId(); const now = Date.now(); const seed = Math.floor(Math.random() * 2 ** 31); const versionNonce = Math.floor(Math.random() * 2 ** 31); const element = { id, type: params.type, x: params.x, y: params.y, width: params.width ?? 10, height: params.height ?? 10, seed, version: 1, versionNonce, isDeleted: false, locked: params.locked ?? false, angle: params.angle ?? 0, fillStyle: params.fillStyle ?? 'hachure', strokeWidth: params.strokeWidth ?? 1, strokeStyle: params.strokeStyle ?? 'solid', roughness: params.roughness ?? 1, opacity: params.opacity !== undefined ? Math.max(0, Math.min(100, params.opacity * 100)) : 100, groupIds: [], frameId: null, roundness: params.roundness ?? null, boundElements: null, link: null, updated: now, strokeColor: params.strokeColor ?? '#000000', backgroundColor: params.backgroundColor ?? 'transparent', text: params.text ?? '', fontSize: params.fontSize ?? 20, fontFamily: params.fontFamily ?? 1, textAlign: params.textAlign ?? 'center', verticalAlign: params.verticalAlign ?? 'middle', containerId: null, originalText: params.text ?? '', points: params.points, startBinding: null, endBinding: null, lastCommittedPoint: null, startArrowhead: null, endArrowhead: null, fileId: null, scale: [1, 1], status: 'saved', }; if ((element.type === 'arrow' || element.type === 'line') && (!element.points || element.points.length < 2)) { element.points = [[0, 0], [element.width || 10, element.height || 0]]; if (element.type === 'arrow') { element.startArrowhead = element.startArrowhead ?? null; element.endArrowhead = element.endArrowhead ?? 'arrow'; } } Object.keys(element).forEach(key => { if (element[key] === undefined) delete element[key]; }); elements.set(id, element); return { content: [{ type: 'text', text: JSON.stringify({ id: element.id, type: element.type, created: true }, null, 2) }] }; }
- src/index.js:94-118 (registration)Tool registration in server capabilities, including description and input schema for 'create_element'.create_element: { description: 'Create a new Excalidraw element', inputSchema: { type: 'object', properties: { type: { type: 'string', enum: Object.values(EXCALIDRAW_ELEMENT_TYPES) }, x: { type: 'number' }, y: { type: 'number' }, width: { type: 'number' }, height: { type: 'number' }, backgroundColor: { type: 'string' }, strokeColor: { type: 'string' }, strokeWidth: { type: 'number' }, roughness: { type: 'number' }, opacity: { type: 'number' }, text: { type: 'string' }, fontSize: { type: 'number' }, fontFamily: { type: 'string' } }, required: ['type', 'x', 'y'] } },
- src/index.js:30-46 (schema)Zod schema definition for Excalidraw element properties, used to validate inputs in the create_element handler.const ElementSchema = z.object({ type: z.enum(Object.values(EXCALIDRAW_ELEMENT_TYPES)), x: z.number(), y: z.number(), width: z.number().optional(), height: z.number().optional(), points: z.array(z.object({ x: z.number(), y: z.number() })).optional(), backgroundColor: z.string().optional(), strokeColor: z.string().optional(), strokeWidth: z.number().optional(), roughness: z.number().optional(), opacity: z.number().optional(), text: z.string().optional(), fontSize: z.number().optional(), fontFamily: z.number().optional(), locked: z.boolean().optional() // ADDED: Make sure locked status is saved });