Skip to main content
Glama

read_me

Access the Excalidraw element reference to understand types, colors, sizing, and tips before creating diagrams.

Instructions

Get the Excalidraw element reference: types, colors, sizing, and tips. Call this before creating diagrams.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The main handler function for the read_me tool that returns the cheatsheet content as formatted text
    export async function handleReadMe(): Promise<{
      content: Array<{ type: 'text'; text: string }>;
    }> {
      return {
        content: [{
          type: 'text' as const,
          text: getCheatsheetText(),
        }],
      };
    }
  • Helper function that generates the formatted cheatsheet text with element types, color palettes, sizing guidelines, and tips
    export function getCheatsheetText(): string {
      const ref = ELEMENT_REFERENCE;
      const lines: string[] = [];
    
      lines.push('# Excalidraw MCP Quick Reference\n');
    
      lines.push('## Element Types\n');
      for (const [name, info] of Object.entries(ref.types)) {
        lines.push(`### ${name}`);
        lines.push(info.description);
        lines.push(`Required: ${info.requiredFields.join(', ')}`);
        if (info.optionalFields) {
          lines.push(`Optional: ${info.optionalFields.join(', ')}`);
        }
        if ('defaults' in info && info.defaults) {
          lines.push(`Defaults: ${JSON.stringify(info.defaults)}`);
        }
        if ('example' in info && info.example) {
          lines.push(`Example: ${JSON.stringify(info.example)}`);
        }
        lines.push('');
      }
    
      lines.push('## Color Palettes\n');
      for (const [name, palette] of Object.entries(ref.colorPalettes)) {
        lines.push(`### ${name} - ${palette.description}`);
        for (const [colorName, hex] of Object.entries(palette.colors)) {
          lines.push(`  ${colorName}: ${hex}`);
        }
        lines.push('');
      }
    
      lines.push('## Sizing Guidelines\n');
      for (const [key, val] of Object.entries(ref.sizing)) {
        if (typeof val === 'string') {
          lines.push(`- ${key}: ${val}`);
        } else {
          lines.push(`- ${key}:`);
          for (const [k, v] of Object.entries(val)) {
            lines.push(`    ${k}: ${v}px`);
          }
        }
      }
      lines.push('');
    
      lines.push('## Tips\n');
      for (const tip of ref.tips) {
        lines.push(`- ${tip}`);
      }
    
      return lines.join('\n');
    }
  • Data structure defining all element types, color palettes, sizing rules, and best practices that the read_me tool returns
    export const ELEMENT_REFERENCE = {
      types: {
        rectangle: {
          description: 'Rectangular shape. Use for boxes, containers, cards.',
          requiredFields: ['x', 'y'],
          optionalFields: ['width', 'height', 'backgroundColor', 'strokeColor', 'text'],
          defaults: { width: 200, height: 100 },
        },
        ellipse: {
          description: 'Oval/circle shape. Use for nodes, badges, indicators.',
          requiredFields: ['x', 'y'],
          optionalFields: ['width', 'height', 'backgroundColor', 'strokeColor', 'text'],
          defaults: { width: 150, height: 150 },
        },
        diamond: {
          description: 'Diamond/rhombus shape. Use for decision points in flowcharts.',
          requiredFields: ['x', 'y'],
          optionalFields: ['width', 'height', 'backgroundColor', 'strokeColor', 'text'],
          defaults: { width: 150, height: 150 },
        },
        arrow: {
          description: 'Directional arrow connecting points. Use for flows and relationships.',
          requiredFields: ['x', 'y', 'points'],
          optionalFields: ['strokeColor', 'strokeWidth'],
          example: { x: 0, y: 0, points: [{ x: 0, y: 0 }, { x: 200, y: 0 }] },
        },
        line: {
          description: 'Straight or polyline segment. Use for dividers, connections without direction.',
          requiredFields: ['x', 'y', 'points'],
          optionalFields: ['strokeColor', 'strokeWidth'],
        },
        text: {
          description: 'Standalone text label. Use for titles, annotations, labels.',
          requiredFields: ['x', 'y', 'text'],
          optionalFields: ['fontSize', 'fontFamily'],
          defaults: { fontSize: 20 },
        },
        freedraw: {
          description: 'Freehand drawing path. Use for sketchy annotations.',
          requiredFields: ['x', 'y', 'points'],
          optionalFields: ['strokeColor', 'strokeWidth'],
        },
      },
    
      colorPalettes: {
        excalidraw: {
          description: 'Default Excalidraw hand-drawn palette',
          colors: {
            blue: '#1971c2',
            red: '#c92a2a',
            green: '#2f9e44',
            orange: '#e67700',
            yellow: '#f59f00',
            purple: '#6741d9',
            pink: '#c2255c',
            gray: '#868e96',
            black: '#1b1b1f',
            white: '#ffffff',
          },
        },
        pastel: {
          description: 'Soft pastel backgrounds for containers and cards',
          colors: {
            lightBlue: '#d0ebff',
            lightRed: '#ffe3e3',
            lightGreen: '#d3f9d8',
            lightOrange: '#fff4e6',
            lightYellow: '#fff9db',
            lightPurple: '#e5dbff',
            lightPink: '#ffdeeb',
            lightGray: '#f1f3f5',
          },
        },
      },
    
      sizing: {
        spacing: 'Keep 40-60px between elements for readable layouts',
        textInBox: 'Add 20px padding around text inside rectangles',
        arrowGap: 'Start arrows 10px from source edge, end 10px before target',
        minWidth: 'Minimum readable element width is 80px',
        fontSize: {
          title: 28,
          heading: 22,
          body: 16,
          caption: 12,
        },
      },
    
      tips: [
        'Use batch_create_elements to place multiple elements at once - faster than individual creates',
        'Group related elements with group_elements after creating them',
        'Use align_elements and distribute_elements to clean up layouts',
        'For flowcharts: diamond = decision, rectangle = process, ellipse = start/end',
        'Set roughness: 0 for clean lines, 1 for hand-drawn look, 2 for sketchy',
        'Lock elements with lock_elements to prevent accidental changes to finished sections',
      ],
    };
  • Registration of the read_me tool with the MCP server, including its description and handler wiring
    // Register read_me as a regular tool (no UI needed)
    server.tool(
      'read_me',
      'Get the Excalidraw element reference: types, colors, sizing, and tips. Call this before creating diagrams.',
      {},
      async () => {
        try {
          return await handleReadMe();
        } catch (err) {
          return {
            content: [{ type: 'text' as const, text: `Error: ${(err as Error).message}` }],
            isError: true,
          };
        }
      }
    );
  • src/mcp/index.ts:58-72 (registration)
    Calls registerMcpApps to register the read_me tool along with other MCP Apps tools and resources
    // Register MCP Apps tools (create_view, read_me) and widget resource
    const __dirname = path.dirname(fileURLToPath(import.meta.url));
    registerMcpApps(server, {
      getWidgetHtml: async () => {
        const widgetPath = path.resolve(__dirname, '../widget/index.html');
        try {
          return await fs.promises.readFile(widgetPath, 'utf-8');
        } catch {
          return '<html><body><p>Widget not built. Run npm run build:widget</p></body></html>';
        }
      },
      persistToStore: async (elements) => {
        await client.batchCreate(elements);
      },
    });

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/debu-sinha/excalidraw-mcp-server'

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