create-simple-pdf
Generate basic PDF documents with text content using this simplified tool. Supports emoji rendering and document title metadata for straightforward PDF creation.
Instructions
Create a simple PDF with just text content. A simplified version of create-pdf for basic use cases. Supports emoji rendering.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filename | No | Optional filename for the PDF (defaults to "document.pdf"). SECURITY: Filenames are sanitized and written to a sandboxed directory: • Default: ~/.mcp-pdf/ • Override: Set PDF_OUTPUT_DIR environment variable • Path traversal attempts (.., /, etc) are blocked • Only alphanumeric, spaces, hyphens, underscores, and dots allowed • If file exists, timestamp is appended automatically | |
| text | Yes | Text content for the PDF | |
| title | No | Document title metadata |
Input Schema (JSON Schema)
{
"properties": {
"filename": {
"description": "Optional filename for the PDF (defaults to \"document.pdf\").\n\nSECURITY: Filenames are sanitized and written to a sandboxed directory:\n• Default: ~/.mcp-pdf/\n• Override: Set PDF_OUTPUT_DIR environment variable\n• Path traversal attempts (.., /, etc) are blocked\n• Only alphanumeric, spaces, hyphens, underscores, and dots allowed\n• If file exists, timestamp is appended automatically",
"type": "string"
},
"text": {
"description": "Text content for the PDF",
"type": "string"
},
"title": {
"description": "Document title metadata",
"type": "string"
}
},
"required": [
"text"
],
"type": "object"
}
Implementation Reference
- src/tools/create-simple-pdf.ts:29-70 (handler)The async handler function that executes the tool: creates PDFDocument, handles emoji rendering, generates PDF buffer, saves to file with UUID, returns success message with resource info or error.async (args: CreateSimplePdfArgs) => { const { filename = 'document.pdf', text, title } = args; try { const doc = new PDFDocument({ info: { ...(title && { Title: title }), ...(filename && { Subject: filename }), }, }); const chunks: Buffer[] = []; doc.on('data', (c: Buffer) => chunks.push(c)); const pdfPromise = new Promise<Buffer>((resolve, reject) => { doc.on('end', () => resolve(Buffer.concat(chunks))); doc.on('error', reject); }); const containsEmoji = hasEmoji(text); const emojiAvailable = containsEmoji ? registerEmojiFont() : false; const fonts = await setupFonts(doc); const { regular: regularFont } = fonts; renderTextWithEmoji(doc, text, 12, regularFont, emojiAvailable); doc.end(); const pdfBuffer = await pdfPromise; const uuid = crypto.randomUUID(); const storedFilename = `${uuid}.pdf`; const { fullPath } = await writePdfToFile(pdfBuffer, storedFilename, config.storageDir); const includePath = config.includePath; return { content: [ { type: 'text' as const, text: ['PDF created successfully', `Resource: mcp-pdf://${uuid}`, includePath ? `Output: ${fullPath}` : undefined, `Size: ${pdfBuffer.length} bytes`, filename !== 'document.pdf' ? `Filename: ${filename}` : undefined].filter(Boolean).join('\n'), }, ], }; } catch (error) { const message = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text' as const, text: `Error creating PDF: ${message}` }], isError: true }; } }
- src/tools/create-simple-pdf.ts:23-27 (schema)Zod-based input schema defining parameters: filename (optional), text (required), title (optional).inputSchema: { filename: z.string().optional().describe('Optional logical filename (metadata only). Storage uses UUID. Defaults to "document.pdf".'), text: z.string().describe('Text content for the PDF'), title: z.string().optional().describe('Document title metadata'), } as Record<string, z.ZodTypeAny>,
- src/server.ts:27-27 (registration)Top-level registration call that invokes the tool's register function to add 'create-simple-pdf' tool to the MCP server.registerCreateSimplePdfTool(server, serverConfig);
- src/tools/create-simple-pdf.ts:17-72 (registration)The registration function exported by the tool module, which calls server.registerTool with name, spec (title, desc, schema), and handler.export function registerCreateSimplePdfTool(server: McpServer, config: PdfServerConfig) { server.registerTool( 'create-simple-pdf', { title: 'Create Simple PDF', description: 'Create a simple PDF with just text content. Supports emoji rendering.', inputSchema: { filename: z.string().optional().describe('Optional logical filename (metadata only). Storage uses UUID. Defaults to "document.pdf".'), text: z.string().describe('Text content for the PDF'), title: z.string().optional().describe('Document title metadata'), } as Record<string, z.ZodTypeAny>, }, async (args: CreateSimplePdfArgs) => { const { filename = 'document.pdf', text, title } = args; try { const doc = new PDFDocument({ info: { ...(title && { Title: title }), ...(filename && { Subject: filename }), }, }); const chunks: Buffer[] = []; doc.on('data', (c: Buffer) => chunks.push(c)); const pdfPromise = new Promise<Buffer>((resolve, reject) => { doc.on('end', () => resolve(Buffer.concat(chunks))); doc.on('error', reject); }); const containsEmoji = hasEmoji(text); const emojiAvailable = containsEmoji ? registerEmojiFont() : false; const fonts = await setupFonts(doc); const { regular: regularFont } = fonts; renderTextWithEmoji(doc, text, 12, regularFont, emojiAvailable); doc.end(); const pdfBuffer = await pdfPromise; const uuid = crypto.randomUUID(); const storedFilename = `${uuid}.pdf`; const { fullPath } = await writePdfToFile(pdfBuffer, storedFilename, config.storageDir); const includePath = config.includePath; return { content: [ { type: 'text' as const, text: ['PDF created successfully', `Resource: mcp-pdf://${uuid}`, includePath ? `Output: ${fullPath}` : undefined, `Size: ${pdfBuffer.length} bytes`, filename !== 'document.pdf' ? `Filename: ${filename}` : undefined].filter(Boolean).join('\n'), }, ], }; } catch (error) { const message = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text' as const, text: `Error creating PDF: ${message}` }], isError: true }; } } ); }