docx-save
Save DOCX documents to disk by specifying document ID and file path. This tool enables persistent storage of Word documents created or modified through the DOCX MCP Server.
Instructions
Persist the docx to disk path by id.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| path | Yes |
Implementation Reference
- src/index.ts:202-209 (handler)The main handler logic for the 'docx-save' tool. It parses the input arguments (id and output path), packs the document into a buffer using the registry, ensures the output directory exists, writes the buffer to the specified file path, and returns the id, path, and byte length.case "docx-save": { const { id, path: outPath } = parseArgs<{ id: string; path: string }>(args, tools["docx-save"].inputSchema); const buf = await registry.packToBuffer(id); const dir = path.dirname(outPath); await mkdir(dir, { recursive: true }); await writeFile(outPath, buf); return ok({ id, path: outPath, bytes: buf.byteLength }); }
- src/index.ts:73-76 (schema)The input schema and description for the 'docx-save' tool, defining required parameters 'id' (string) and 'path' (string)."docx-save": { description: "Persist the docx to disk path by id.", inputSchema: { type: "object", required: ["id", "path"], properties: { id: { type: "string" }, path: { type: "string" } } } },
- src/index.ts:101-103 (registration)Registration for listing tools, which includes 'docx-save' via the 'tools' object.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: Object.entries(tools).map(([name, t]) => ({ name, description: t.description, inputSchema: t.inputSchema as any })) }));
- src/index.ts:105-229 (registration)Registration for calling tools via switch statement on tool name, dispatching to 'docx-save' handler.server.setRequestHandler(CallToolRequestSchema, async (req) => { const { name, arguments: args } = req.params; try { switch (name) { case "docx-getSchema": { return ok({ schema: DocxSchema, description: "JSON Schema for DOCX document structure. Use this to understand the format before creating or editing documents.", examples: { simpleDocument: { meta: { title: "Sample Document", creator: "Agent" }, content: [ { type: "heading", level: 1, children: [{ type: "text", text: "Title" }] }, { type: "paragraph", children: [{ type: "text", text: "Hello ", bold: true }, { type: "text", text: "world" }] } ] }, withTable: { meta: { title: "Document with Table" }, content: [ { type: "heading", level: 1, children: [{ type: "text", text: "Data Table" }] }, { type: "table", rows: [ { cells: [{ children: [{ type: "paragraph", children: [{ type: "text", text: "Header 1" }] }] }] }, { cells: [{ children: [{ type: "paragraph", children: [{ type: "text", text: "Data 1" }] }] }] } ] } ] }, withImages: { meta: { title: "Document with Images" }, content: [ { type: "heading", level: 1, children: [{ type: "text", text: "Images Example" }] }, { type: "paragraph", children: [{ type: "text", text: "Image from URL:" }] }, { type: "image", url: "https://via.placeholder.com/300x200", width: 300, height: 200 }, { type: "paragraph", children: [{ type: "text", text: "Image from local file:" }] }, { type: "image", path: "C:\\path\\to\\image.png", width: 300, height: 200 }, { type: "paragraph", children: [{ type: "text", text: "Image from base64 data:" }] }, { type: "image", data: "iVBORw0KGgoAAAANS...", format: "png", width: 150, height: 100 } ] } } }); } case "docx-create": { const { json } = parseArgs<{ json: any }>(args, tools["docx-create"].inputSchema); const id = nanoid(); // Check if JSON contains images with local paths or URLs const jsonStr = JSON.stringify(json); const hasImagePaths = jsonStr.includes('"path"') || jsonStr.includes('"url"'); if (hasImagePaths) { // Use async version for images with local paths or URLs const { id: docId } = await registry.createAsync(id, json); return ok({ id: docId }); } else { // Use sync version for base64 images or no images const { id: docId } = registry.create(id, json); return ok({ id: docId }); } } case "docx-open": { const { id, path: filePath } = parseArgs<{ id?: string; path: string }>(args, tools["docx-open"].inputSchema); const json = await parseDocxFileToJson(filePath); const docId = id ?? nanoid(); registry.open(docId, json); return ok({ id: docId }); } case "docx-queryMeta": { const { id } = parseArgs<{ id: string }>(args, tools["docx-queryMeta"].inputSchema); return ok(registry.queryMeta(id)); } case "docx-queryObjects": { const { id } = parseArgs<{ id: string }>(args, tools["docx-queryObjects"].inputSchema); return ok(registry.queryObjects(id)); } case "docx-editMeta": { const { id, patch } = parseArgs<{ id: string; patch: any }>(args, tools["docx-editMeta"].inputSchema); const res = registry.editMeta(id, patch); return ok({ id: res.id, updatedAt: res.updatedAt, meta: res.json.meta }); } case "docx-editContent": { const { id, index, block } = parseArgs<{ id: string; index: number; block: any }>(args, tools["docx-editContent"].inputSchema); const res = registry.editContent(id, index, block); return ok({ id: res.id, updatedAt: res.updatedAt }); } case "docx-insertContent": { const { id, index, block } = parseArgs<{ id: string; index: number; block: any }>(args, tools["docx-insertContent"].inputSchema); const res = registry.insertContent(id, index, block); return ok({ id: res.id, updatedAt: res.updatedAt }); } case "docx-removeContent": { const { id, index } = parseArgs<{ id: string; index: number }>(args, tools["docx-removeContent"].inputSchema); const res = registry.removeContent(id, index); return ok({ id: res.id, updatedAt: res.updatedAt }); } case "docx-save": { const { id, path: outPath } = parseArgs<{ id: string; path: string }>(args, tools["docx-save"].inputSchema); const buf = await registry.packToBuffer(id); const dir = path.dirname(outPath); await mkdir(dir, { recursive: true }); await writeFile(outPath, buf); return ok({ id, path: outPath, bytes: buf.byteLength }); } case "docx-openFile": { const { id, path: filePath } = parseArgs<{ id?: string; path: string }>(args, tools["docx-openFile"].inputSchema); const json = await parseDocxFileToJson(filePath); const docId = id ?? nanoid(); registry.open(docId, json); return ok({ id: docId }); } case "docx-exportJson": { const { id } = parseArgs<{ id: string }>(args, tools["docx-exportJson"].inputSchema); const doc = registry.get(id); if (!doc) throw new McpError(ErrorCode.InvalidParams, `doc not found: ${id}`); return ok(doc.json); } default: throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`); } } catch (err: any) { throw new McpError(ErrorCode.InternalError, err?.message ?? String(err)); } });