generate_word_document
Create professional Word documents with formatted sections, tables, charts, and table of contents from analysis data using Microsoft 365 services.
Instructions
Create professional Word documents with formatted sections, tables, charts, and table of contents from analysis data.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Action: create new document, get existing, list all, export to format, or append content | |
| fileName | No | Name for the new document file (for create action) | |
| driveId | No | OneDrive/SharePoint drive ID (default: user's OneDrive) | |
| folderId | No | Folder ID within the drive (default: root) | |
| template | No | Template configuration for document styling | |
| sections | No | Array of content sections to create | |
| fileId | No | File ID for get/export/append actions | |
| format | No | Export format (for export action) | |
| content | No | Content to append (for append action) | |
| filter | No | OData filter for list action | |
| top | No | Number of results to return (for list action) |
Implementation Reference
- src/server.ts:1289-1308 (registration)Registers the 'generate_word_document' tool with MCP server, linking to handleWordDocuments handler and wordDocumentArgsSchema"generate_word_document", "Create professional Word documents with formatted sections, tables, charts, and table of contents from analysis data.", wordDocumentArgsSchema.shape, {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false}, wrapToolHandler(async (args: WordDocumentArgs) => { this.validateCredentials(); try { const result = await handleWordDocuments(args, this.getGraphClient()); return { content: [{ type: 'text', text: result }] }; } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Error generating Word document: ${error instanceof Error ? error.message : 'Unknown error'}` ); } }) );
- Main handler function for Word document operations, dispatches to specific actions like create (which generates the document)export async function handleWordDocuments( args: WordDocumentArgs, graphClient: Client ): Promise<string> { try { switch (args.action) { case 'create': return await createDocument(args, graphClient); case 'get': return await getDocument(args, graphClient); case 'list': return await listDocuments(args, graphClient); case 'export': return await exportDocument(args, graphClient); case 'append': return await appendToDocument(args, graphClient); default: throw new McpError( ErrorCode.InvalidRequest, `Unknown action: ${args.action}` ); } } catch (error) { if (error instanceof McpError) throw error; throw new McpError( ErrorCode.InternalError, `Word document operation failed: ${error instanceof Error ? error.message : 'Unknown error'}` ); } }
- Core generation logic for creating Word documents from sections and template, generates XML content and uploads via Graph APIasync function createDocument( args: WordDocumentArgs, graphClient: Client ): Promise<string> { if (!args.fileName) { throw new McpError(ErrorCode.InvalidRequest, 'fileName is required for create action'); } if (!args.sections || args.sections.length === 0) { throw new McpError(ErrorCode.InvalidRequest, 'At least one section is required'); } // Determine drive location (default to user's OneDrive) const driveId = args.driveId || 'me'; const folderPath = args.folderId ? `/items/${args.folderId}` : '/root'; // Create Word document file const fileName = args.fileName.endsWith('.docx') ? args.fileName : `${args.fileName}.docx`; // Generate document content const documentContent = generateDocumentXML(args.sections, args.template); const uploadedFile = await graphClient .api(`/drives/${driveId}${folderPath}:/${fileName}:/content`) .header('Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') .put(documentContent); return JSON.stringify({ success: true, fileId: uploadedFile.id, fileName: uploadedFile.name, webUrl: uploadedFile.webUrl, driveId: uploadedFile.parentReference?.driveId, message: `Word document "${fileName}" created successfully with ${args.sections.length} sections` }, null, 2); }
- Zod schema defining input parameters for generate_word_document tool, including sections, template, file locationsexport const wordDocumentArgsSchema = z.object({ action: z.enum(['create', 'get', 'list', 'export', 'append']) .describe('Action: create new document, get existing, list all, export to format, or append content'), fileName: z.string().optional() .describe('Name for the new document file (for create action)'), driveId: z.string().optional() .describe('OneDrive/SharePoint drive ID (default: user\'s OneDrive)'), folderId: z.string().optional() .describe('Folder ID within the drive (default: root)'), template: wordTemplateSchema.optional() .describe('Template configuration for document styling'), sections: z.array(wordSectionSchema).optional() .describe('Array of content sections to create'), fileId: z.string().optional() .describe('File ID for get/export/append actions'), format: z.enum(['docx', 'pdf', 'html', 'txt']).optional() .describe('Export format (for export action)'), content: z.string().optional() .describe('Content to append (for append action)'), filter: z.string().optional() .describe('OData filter for list action'), top: z.number().optional() .describe('Number of results to return (for list action)') });
- Generates Word document XML content from sections and template (core document building logic)function generateDocumentXML(sections: WordSection[], template?: WordTemplate): Buffer { // This is a simplified implementation // For production, integrate with docx library: https://docx.js.org/ let content = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"> <w:body>`; // Add header if specified if (template?.header) { content += ` <w:p> <w:pPr> <w:pStyle w:val="Header"/> </w:pPr> <w:r> <w:t>${escapeXml(template.header)}</w:t> </w:r> </w:p>`; } // Add sections sections.forEach(section => { content += generateSectionXML(section); }); // Add footer if specified if (template?.footer) { content += ` <w:p> <w:pPr> <w:pStyle w:val="Footer"/> </w:pPr> <w:r> <w:t>${escapeXml(template.footer)}</w:t> </w:r> </w:p>`; } content += ` </w:body> </w:document>`; return Buffer.from(content, 'utf-8'); }