Skip to main content
Glama
yctimlin

Excalidraw MCP Server

by yctimlin

create_element

Generate and customize Excalidraw elements (shapes, text, lines) with precise positioning, dimensions, colors, and styles via a structured API for diagram creation and modification.

Instructions

Create a new Excalidraw element

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
backgroundColorNo
fontFamilyNo
fontSizeNo
heightNo
opacityNo
roughnessNo
strokeColorNo
strokeWidthNo
textNo
typeYes
widthNo
xYes
yYes

Implementation Reference

  • Main handler for the 'create_element' MCP tool: parses input with ElementSchema, generates ID, converts text to label format, calls createElementOnCanvas to sync to the canvas server, and returns success response.
    case 'create_element': {
      const params = ElementSchema.parse(args);
      logger.info('Creating element via MCP', { type: params.type });
    
      const id = generateId();
      const element: ServerElement = {
        id,
        ...params,
        createdAt: new Date().toISOString(),
        updatedAt: new Date().toISOString(),
        version: 1
      };
    
      // Convert text to label format for Excalidraw
      const excalidrawElement = convertTextToLabel(element);
      
      // Create element directly on HTTP server (no local storage)
      const canvasElement = await createElementOnCanvas(excalidrawElement);
      
      if (!canvasElement) {
        throw new Error('Failed to create element: HTTP server unavailable');
      }
      
      logger.info('Element created via MCP and synced to canvas', { 
        id: excalidrawElement.id, 
        type: excalidrawElement.type,
        synced: !!canvasElement 
      });
      
      return {
        content: [{ 
          type: 'text', 
          text: `Element created successfully!\n\n${JSON.stringify(canvasElement, null, 2)}\n\n✅ Synced to canvas` 
        }]
      };
    }
  • src/index.ts:233-258 (registration)
    Tool registration in the tools array: defines name 'create_element', description, and JSON inputSchema, used in server capabilities for MCP tool discovery.
    {
      name: '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']
      }
    },
  • Zod schema (ElementSchema) used to parse and validate input arguments in the create_element handler.
    const ElementSchema = z.object({
      type: z.enum(Object.values(EXCALIDRAW_ELEMENT_TYPES) as [ExcalidrawElementType, ...ExcalidrawElementType[]]),
      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.string().optional(),
      groupIds: z.array(z.string()).optional(),
      locked: z.boolean().optional()
    });
  • Helper function called by the handler to perform the actual canvas sync for element creation via POST to /api/elements.
    async function createElementOnCanvas(elementData: ServerElement): Promise<ServerElement | null> {
      const result = await syncToCanvas('create', elementData);
      return result?.element || elementData;
    }
  • Helper function used in handler to convert 'text' property to Excalidraw-compatible 'label' format for non-text elements.
    function convertTextToLabel(element: ServerElement): ServerElement {
      const { text, ...rest } = element;
      if (text) {
        // For standalone text elements, keep text as direct property
        if (element.type === 'text') {
          return element; // Keep text as direct property
        }
        // For other elements (rectangle, ellipse, diamond), convert to label format
        return {
          ...rest,
          label: { text }
        } as ServerElement;
      }
      return element;
    }
Install Server

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