save_scene
Saves the current Excalidraw diagram elements and scene state as a .excalidraw file, enabling easy export and reuse of the workspace. Supports custom filenames for organized storage.
Instructions
Saves the current Excalidraw elements and scene state to a .excalidraw file.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filename | No | Optional filename ending with .excalidraw (default: mcp_scene.excalidraw) |
Implementation Reference
- src/index.js:571-638 (handler)Handler for the 'save_scene' tool: parses parameters, constructs Excalidraw-compatible scene data from in-memory elements and state, handles selected elements conversion and points validation, serializes to JSON, and writes to a .excalidraw file using fs.promises.writeFile.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 }; } }
- src/index.js:80-82 (schema)Zod schema definition for validating the input parameters of the save_scene tool, specifically the optional filename.const SaveSceneSchema = z.object({ filename: z.string().optional().describe("Optional filename ending with .excalidraw (default: mcp_scene.excalidraw)") });
- src/index.js:269-280 (registration)Registration of the save_scene tool in the MCP server capabilities, including description and input schema matching the Zod schema.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)' } } } }