Skip to main content
Glama
Abdullah007bajwa

Excalidraw MCP Server

save_scene

Save Excalidraw diagrams to .excalidraw files for persistent storage and future editing.

Instructions

Saves the current Excalidraw elements and scene state to a .excalidraw file.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
filenameNoOptional filename ending with .excalidraw (default: mcp_scene.excalidraw)

Implementation Reference

  • Handler for the save_scene tool: validates params with SaveSceneSchema, builds Excalidraw-compatible sceneData from elements and sceneState, converts selectedElements Set to object, fixes points for lines/arrows, writes JSON file via fs.promises.writeFile, returns success/error message.
    case 'save_scene': {
      const params = SaveSceneSchema.parse(args || {});
      const filename = params.filename || 'mcp_scene.excalidraw';
    
      if (!filename.endsWith('.excalidraw')) {
        throw new Error("Filename must end with .excalidraw");
      }
    
      // Convert selectedElements Set to the expected object format
      const selectedElementIds = {};
      sceneState.selectedElements.forEach(id => {
        selectedElementIds[id] = true;
      });
    
      // Ensure all elements have points in the correct format
      const elementsToSave = Array.from(elements.values()).map(el => {
        if ((el.type === 'arrow' || el.type === 'line') && (!el.points || el.points.length < 2)) {
          logger.warn(`Element ${el.id} of type ${el.type} has invalid/missing points. Adding default points.`);
          el.points = [[0, 0], [el.width || 10, el.height || 0]];
        }
        return el;
      });
    
      const sceneData = {
        type: "excalidraw",
        version: 2,
        source: "mcp-server",
        elements: elementsToSave,
        appState: {
          viewBackgroundColor: sceneState.viewBackgroundColor ?? "#ffffff",
          scrollX: sceneState.viewport?.x ?? 0,
          scrollY: sceneState.viewport?.y ?? 0,
          zoom: { value: sceneState.viewport?.zoom ?? 1 }, // Updated zoom format
          selectedElementIds: selectedElementIds, // Updated selectedElementIds format
          gridSize: null,
          zenModeEnabled: false,
          editingGroupId: null,
          theme: sceneState.theme ?? 'light',
          currentItemStrokeColor: "#000000",
          currentItemBackgroundColor: "transparent",
          currentItemFillStyle: "hachure",
          currentItemStrokeWidth: 1,
          currentItemStrokeStyle: "solid",
          currentItemRoughness: 1,
          currentItemOpacity: 100,
          currentItemFontFamily: 1,
          currentItemFontSize: 20,
          currentItemTextAlign: "center",
          currentItemStartArrowhead: null,
          currentItemEndArrowhead: "arrow",
        },
        files: {}
      };
    
      try {
        await fs.writeFile(filename, JSON.stringify(sceneData, null, 2), 'utf8');
        logger.info(`Scene saved successfully to ${filename}`);
        return {
          content: [{ type: 'text', text: `Scene saved successfully to ${filename}` }]
        };
      } catch (error) {
        logger.error(`Error saving scene: ${error.message}`, { error });
        return {
          content: [{ type: 'text', text: `Error saving scene: ${error.message}` }],
          isError: true
        };
      }
    }
  • Zod schema defining the input for save_scene: optional filename string.
    // ADDED: Schema for the new save_scene tool
    const SaveSceneSchema = z.object({
      filename: z.string().optional().describe("Optional filename ending with .excalidraw (default: mcp_scene.excalidraw)")
    });
  • src/index.js:268-280 (registration)
    MCP capabilities registration for save_scene tool, specifying description and inputSchema (note: inputSchema duplicated from zod schema).
    // ADDED: Definition for the save_scene tool
    save_scene: {
      description: 'Saves the current Excalidraw elements and scene state to a .excalidraw file.',
      inputSchema: {
        type: 'object',
        properties: {
          filename: {
            type: 'string',
            description: 'Optional filename ending with .excalidraw (default: mcp_scene.excalidraw)'
          }
        }
      }
    }
  • src/index.js:841-853 (registration)
    Registration of save_scene in the ListToolsRequestSchema handler response.
    {
      name: 'save_scene',
      description: 'Saves the current Excalidraw elements and scene state to a .excalidraw file.',
      inputSchema: {
        type: 'object',
        properties: {
          filename: {
            type: 'string',
            description: 'Optional filename ending with .excalidraw (default: mcp_scene.excalidraw)'
          }
        }
      }
    }

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/Abdullah007bajwa/mcp_excalidraw'

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