Skip to main content
Glama
yctimlin

Excalidraw MCP Server

by yctimlin

update_element

Modify properties of existing Excalidraw elements, such as position, size, colors, text, and style, to refine or update diagrams programmatically.

Instructions

Update an existing Excalidraw element

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
backgroundColorNo
fontFamilyNo
fontSizeNo
heightNo
idYes
opacityNo
roughnessNo
strokeColorNo
strokeWidthNo
textNo
typeNo
widthNo
xNo
yNo

Implementation Reference

  • Main handler for the 'update_element' MCP tool. Validates input using Zod schemas, constructs the update payload, converts text to Excalidraw label format if needed, syncs the update to the canvas via HTTP API using updateElementOnCanvas helper, and returns a success response with the updated element details.
    case 'update_element': { const params = ElementIdSchema.merge(ElementSchema.partial()).parse(args); const { id, ...updates } = params; if (!id) throw new Error('Element ID is required'); // Build update payload with timestamp and version increment const updatePayload: Partial<ServerElement> & { id: string } = { id, ...updates, updatedAt: new Date().toISOString() }; // Convert text to label format for Excalidraw const excalidrawElement = convertTextToLabel(updatePayload as ServerElement); // Update element directly on HTTP server (no local storage) const canvasElement = await updateElementOnCanvas(excalidrawElement); if (!canvasElement) { throw new Error('Failed to update element: HTTP server unavailable or element not found'); } logger.info('Element updated via MCP and synced to canvas', { id: excalidrawElement.id, synced: !!canvasElement }); return { content: [{ type: 'text', text: `Element updated successfully!\n\n${JSON.stringify(canvasElement, null, 2)}\n\n✅ Synced to canvas` }] }; }
  • src/index.ts:259-285 (registration)
    Registration of the 'update_element' tool in the MCP tools array, including name, description, and JSON input schema definition.
    { name: 'update_element', description: 'Update an existing Excalidraw element', inputSchema: { type: 'object', properties: { id: { type: 'string' }, 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: ['id'] } },
  • Helper function that performs the actual canvas sync for element updates by calling the generic syncToCanvas function with 'update' operation.
    async function updateElementOnCanvas(elementData: Partial<ServerElement> & { id: string }): Promise<ServerElement | null> { const result = await syncToCanvas('update', elementData); return result?.element || null; }
  • Zod schema used by the Express server PUT /api/elements/:id endpoint for validating update requests, which is called by the MCP tool's sync helper.
    const UpdateElementSchema = z.object({ id: z.string(), type: z.enum(Object.values(EXCALIDRAW_ELEMENT_TYPES) as [ExcalidrawElementType, ...ExcalidrawElementType[]]).optional(), x: z.number().optional(), y: z.number().optional(), width: z.number().optional(), height: 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(), label: z.object({ text: z.string() }).optional(), fontSize: z.number().optional(), fontFamily: z.string().optional(), groupIds: z.array(z.string()).optional(), locked: z.boolean().optional() });
  • Backend Express handler for PUT /api/elements/:id, which performs the actual element update in memory storage, broadcasts via WebSocket, and returns the updated element. Called indirectly by MCP tool via HTTP sync.
    app.put('/api/elements/:id', (req: Request, res: Response) => { try { const { id } = req.params; const updates = UpdateElementSchema.parse({ id, ...req.body }); if (!id) { return res.status(400).json({ success: false, error: 'Element ID is required' }); } const existingElement = elements.get(id); if (!existingElement) { return res.status(404).json({ success: false, error: `Element with ID ${id} not found` }); } const updatedElement: ServerElement = { ...existingElement, ...updates, updatedAt: new Date().toISOString(), version: (existingElement.version || 0) + 1 }; elements.set(id, updatedElement); // Broadcast to all connected clients const message: ElementUpdatedMessage = { type: 'element_updated', element: updatedElement }; broadcast(message); res.json({ success: true, element: updatedElement }); } catch (error) { logger.error('Error updating element:', error); res.status(400).json({ success: false, error: (error as Error).message }); } });

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yctimlin/mcp_excalidraw'

If you have feedback or need assistance with the MCP directory API, please join our Discord server