create_invoice_pdf
Generate professional PDF invoices from structured data with customizable templates, tax rates, and line items for business documentation.
Instructions
Generate a PDF invoice file
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| invoice_data | Yes | Complete invoice data including company info, bill-to info, items, etc. | |
| filename | No | Optional custom filename for the PDF (without .pdf extension) |
Implementation Reference
- src/invoice-generator.ts:71-199 (handler)The `generateInvoicePDF` function, which handles the actual conversion of invoice data into a PDF file using puppeteer.
export async function generateInvoicePDF( invoiceData: InvoiceData, customFilename?: string ): Promise<string> { // Calculate totals const subtotal = invoiceData.items.reduce((sum, item) => sum + item.amount, 0); const taxAmount = subtotal * (invoiceData.taxRate || 0) / 100; const total = subtotal + taxAmount + (invoiceData.other || 0); // Generate HTML const html = generateInvoiceHTML({ ...invoiceData, subtotal, taxAmount, total, }); // Determine output directory and ensure it exists const outputDir = getOutputDirectory(); console.log(`Using output directory: ${outputDir}`); try { await ensureDirectoryExists(outputDir); } catch (error) { console.error('Directory creation failed, trying alternative locations...'); // Try alternative directories const fallbackDirs = [ path.join(process.cwd(), 'temp'), path.join(__dirname, 'temp'), process.env.TMPDIR || process.env.TMP || '/tmp', ]; let successDir: string | null = null; for (const dir of fallbackDirs) { try { await ensureDirectoryExists(dir); successDir = dir; console.log(`Successfully using fallback directory: ${dir}`); break; } catch (fallbackError) { console.log(`Failed to use fallback directory ${dir}:`, fallbackError); continue; } } if (!successDir) { throw new Error('Unable to create any output directory. Please check file system permissions.'); } } // Generate filename const safeInvoiceNumber = invoiceData.invoiceNumber.replace(/[^a-zA-Z0-9]/g, '_'); const filename = customFilename || `invoice-${safeInvoiceNumber}-${Date.now()}`; const pdfPath = path.join(outputDir, `${filename}.pdf`); console.log(`Generating PDF at: ${pdfPath}`); // Launch browser and generate PDF let browser; try { browser = await puppeteer.launch({ headless: true, args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-gpu', '--disable-web-security', '--disable-extensions', '--no-first-run', '--disable-default-apps', ], }); const page = await browser.newPage(); await page.setContent(html, { waitUntil: 'networkidle0' }); // Test if we can write to the output path try { await page.pdf({ path: pdfPath, format: 'A4', printBackground: true, margin: { top: '20px', right: '20px', bottom: '20px', left: '20px', }, }); // Verify the file was created await fs.access(pdfPath); console.log(`PDF successfully created at: ${pdfPath}`); } catch (pdfError) { console.error('Failed to create PDF at specified path:', pdfError); // Try creating in temp directory as absolute fallback const tempPath = path.join(process.env.TMPDIR || '/tmp', `${filename}.pdf`); console.log(`Trying fallback path: ${tempPath}`); await page.pdf({ path: tempPath, format: 'A4', printBackground: true, margin: { top: '20px', right: '20px', bottom: '20px', left: '20px', }, }); return tempPath; } return pdfPath; } catch (error) { console.error('Error in PDF generation:', error); throw new Error(`PDF generation failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } finally { if (browser) { await browser.close(); } } } - src/index.ts:143-157 (registration)The case handler for 'create_invoice_pdf' in the `index.ts` file, where the tool is called within the MCP server's request handler.
case 'create_invoice_pdf': { const invoiceData = InvoiceDataSchema.parse(args.invoice_data); const filename = args.filename as string | undefined; const pdfPath = await generateInvoicePDF(invoiceData, filename); return { content: [ { type: 'text', text: `Invoice PDF generated successfully at: ${pdfPath}`, }, ], }; } - src/index.ts:15-15 (schema)The `InvoiceDataSchema` definition used for validating the input arguments of the tool.
const InvoiceDataSchema = z.object({