Skip to main content
Glama

write_pdf

Create new PDF files from markdown content or modify existing PDFs by inserting or deleting pages using Desktop Commander MCP's file management capabilities.

Instructions

                    Create a new PDF file or modify an existing one.

                    THIS IS THE ONLY TOOL FOR CREATING AND MODIFYING PDF FILES.

                    RULES ABOUT FILENAMES:
                    - When creating a new PDF, 'outputPath' MUST be provided and MUST use a new unique filename (e.g., "result_01.pdf", "analysis_2025_01.pdf", etc.).

                    MODES:
                    1. CREATE NEW PDF:
                       - Pass a markdown string as 'content'.
                       write_pdf(path="doc.pdf", content="# Title\n\nBody text...")

                    2. MODIFY EXISTING PDF:
                       - Pass array of operations as 'content'.
                       - NEVER overwrite the original file.
                       - ALWAYS provide a new filename in 'outputPath'.
                       - After modifying, show original file path and new file path to user.

                       write_pdf(path="doc.pdf", content=[
                           { type: "delete", pageIndexes: [0, 2] },
                           { type: "insert", pageIndex: 1, markdown: "# New Page" }
                       ])

                    OPERATIONS:
                    - delete: Remove pages by 0-based index.
                      { type: "delete", pageIndexes: [0, 1, 5] }

                    - insert: Add pages at a specific 0-based index.
                      { type: "insert", pageIndex: 0, markdown: "..." }
                      { type: "insert", pageIndex: 5, sourcePdfPath: "/path/to/source.pdf" }

                    PAGE BREAKS:
                    To force a page break, use this HTML element:
                    <div style="page-break-before: always;"></div>
                    
                    Example:
                    "# Page 1\n\n<div style=\"page-break-before: always;\"></div>\n\n# Page 2"

                    ADVANCED STYLING:
                    HTML/CSS and inline SVG are supported for:
                    - Text styling: colors, sizes, alignment, highlights
                    - Boxes: borders, backgrounds, padding, rounded corners
                    - SVG graphics: charts, diagrams, icons, shapes
                    - Images: <img src="/absolute/path/image.jpg" width="300" /> or ![alt](/path/image.jpg)

                    Supports standard markdown features including headers, lists, code blocks, tables, and basic formatting.

                    Only works within allowed directories.

                    IMPORTANT: Always use absolute paths for reliability. Paths are automatically normalized regardless of slash direction. Relative paths may fail as they depend on the current working directory. Tilde paths (~/...) might not work in all contexts. Unless the user explicitly asks for relative paths, use absolute paths.
                    This command can be referenced as "DC: ..." or "use Desktop Commander to ..." in your instructions.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathYes
contentYes
outputPathNo
optionsNo

Implementation Reference

  • MCP handler function for 'write_pdf' tool that validates input using WritePdfArgsSchema and delegates to the writePdf utility function.
    export async function handleWritePdf(args: unknown): Promise<ServerResult> {
        try {
            const parsed = WritePdfArgsSchema.parse(args);
            await writePdf(parsed.path, parsed.content, parsed.outputPath, parsed.options);
            const targetPath = parsed.outputPath || parsed.path;
            return {
                content: [{ type: "text", text: `Successfully wrote PDF to ${targetPath}${parsed.outputPath ? `\nOriginal file: ${parsed.path}` : ''}` }],
            };
        } catch (error) {
            const errorMessage = error instanceof Error ? error.message : String(error);
            return createErrorResponse(errorMessage);
        }
    }
  • Zod schema for validating arguments to the write_pdf tool, supporting both markdown string and PDF operations array.
    export const WritePdfArgsSchema = z.object({
      path: z.string(),
      // Preprocess content to handle JSON strings that should be parsed as arrays
      content: z.preprocess(
        (val) => {
          // If it's a string that looks like JSON array, parse it
          if (typeof val === 'string' && val.trim().startsWith('[')) {
            try {
              return JSON.parse(val);
            } catch {
              // If parsing fails, return as-is (might be markdown content)
              return val;
            }
          }
          // Otherwise return as-is
          return val;
        },
        z.union([z.string(), z.array(PdfOperationSchema)])
      ),
      outputPath: z.string().optional(),
      options: z.object({}).passthrough().optional(), // Allow passing options to md-to-pdf
    });
  • Core utility function implementing PDF creation from markdown or editing existing PDFs using operations like insert/delete pages.
    export async function writePdf(
        filePath: string,
        content: string | PdfOperations[],
        outputPath?: string,
        options: any = {}
    ): Promise<void> {
        const validPath = await validatePath(filePath);
        const fileExtension = getFileExtension(validPath);
    
        if (typeof content === 'string') {
            // --- PDF CREATION MODE ---
            capture('server_write_pdf', {
                fileExtension: fileExtension,
                contentLength: content.length,
                mode: 'create'
            });
    
            const pdfBuffer = await parseMarkdownToPdf(content, options);
            // Use outputPath if provided, otherwise overwrite input file
            const targetPath = outputPath ? await validatePath(outputPath) : validPath;
            await fs.writeFile(targetPath, pdfBuffer);
        } else if (Array.isArray(content)) {
    
            // Use outputPath if provided, otherwise overwrite input file
            const targetPath = outputPath ? await validatePath(outputPath) : validPath;
    
            const operations: PdfOperations[] = [];
    
            // Validate paths in operations
            for (const o of content) {
                if (o.type === 'insert') {
                    if (o.sourcePdfPath) {
                        o.sourcePdfPath = await validatePath(o.sourcePdfPath);
                    }
                }
                operations.push(o);
            }
    
            capture('server_write_pdf', {
                fileExtension: fileExtension,
                operationCount: operations.length,
                mode: 'modify',
                deleteCount: operations.filter(op => op.type === 'delete').length,
                insertCount: operations.filter(op => op.type === 'insert').length
            });
    
            // Perform the PDF editing
            const modifiedPdfBuffer = await editPdf(validPath, operations);
    
            // Write the modified PDF to the output path
            await fs.writeFile(targetPath, modifiedPdfBuffer);
        } else {
            throw new Error('Invalid content type for writePdf. Expected string (markdown) or array of operations.');
        }
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wonderwhy-er/ClaudeComputerCommander'

If you have feedback or need assistance with the MCP directory API, please join our Discord server