Back to the catalog

io.github.kmalakoff/mcp-pdf

MCP server for PDF generation using PDFKit

Open source Open in the app JSON README (API)

About

MCP server for PDF generation using PDFKit

Details

Kind
MCP servers
Topic
Files & documents
Publisher
kmalakoff
Origin
official
Category
ferramentas
Transport
local
Version
1.0.3
Stars
1
Forks
3
Open pull requests
1
Last push
2026-09-05T18:46:24Z
Repository state
ativo
Language
TypeScript
License
MIT
Added
2026-08-29 04:00:21
Updated
2026-08-29 04:00:21
Origin id
io.github.kmalakoff/mcp-pdf

README

# @mcp-z/mcp-pdf

MCP server for creative PDF generation with full emoji, Unicode, and offline support

## Common uses

- Generate PDFs from text or layouts
- Render PDF pages as images
- Measure text before layout

## Transports

MCP supports stdio and HTTP.

**Stdio**
```json
{
  "mcpServers": {
    "pdf": {
      "command": "npx",
      "args": ["-y", "@mcp-z/mcp-pdf"]
    }
  }
}
```

**HTTP**
```json
{
  "mcpServers": {
    "pdf": {
      "type": "http",
      "url": "http://localhost:9010/mcp",
      "start": {
        "command": "npx",
        "args": ["-y", "@mcp-z/mcp-pdf", "--port=9010"]
      }
    }
  }
}
```

`start` is an extension used by `npx @mcp-z/cli up` to launch HTTP servers for you.

## Authentication

No OAuth or API keys required.

## How to use

```bash
# List tools
mcp-z inspect --servers pdf --tools

# Create a simple PDF
mcp-z call pdf pdf-document '{"content":["Hello from MCP"]}'
```

## Available tools

### pdf-resume

Generate professional resumes from JSON Resume format.

Parameters:

- `filename` (string, optional) - Filename for the PDF (defaults to "resume.pdf")
- `resume` (object, required) - JSON Resume schema
- `sections` (object, optional) - Section ordering and field templates
- `layout` (object, optional) - Spatial arrangement (single-column or two-column)
- `styling` (object, optional) - Typography and spacing options
- `font` (string, optional) - Custom font
- `pageSize` (string, optional) - Page size (default: "LETTER")
- `backgroundColor` (string, optional) - Page background color

Resume schema sections:

- `basics` - Name, contact, summary, location
- `work` - Work experience with highlights
- `education` - Degrees and institutions
- `projects` - Personal/professional projects
- `skills` - Skills grouped by category
- `awards`, `certificates`, `languages`, `volunteer`, `publications`, `interests`, `references`

#### Section configuration

Control which sections appear and in what order using `sections.sections`:

```ts
await client.callTool('pdf-resume', {
  resume: { /* JSON Resume data */ },
  sections: {
    sections: [
      { source: 'basics', render: 'header' },
      { source: 'basics.summary', title: 'Summary' },
      { source: 'work', title: 'Experience' },
      { source: 'skills', title: 'Skills' },
      { source: 'education', title: 'Education' }
    ]
  }
});
```

Section config properties:

- `source` (string, required) - Path to data in resume schema (e.g., `basics`, `work`, `meta.customField`)
- `render` (string, optional) - Built-in renderer. Use `header` explicitly or to force a renderer
- `title` (string, optional) - Section heading (omit for no title)
- `template` (string, optional) - LiquidJS template for custom rendering

Available renderers:

- `header` - Name + contact line from basics (never auto-inferred)
- `entry-list` - Arrays with position/institution/organization
- `keyword-list` - Arrays with `keywords`
- `language-list` - Arrays with `language`
- `credential-list` - Arrays with awarder/issuer/publisher
- `reference-list` - Arrays with `reference`
- `text` - String or string array

Example: custom section order with meta fields

```ts
await client.callTool('pdf-resume', {
  resume: {
    basics: { name: 'Jane Doe', email: 'jane@example.com' },
    work: [{ /* ... */ }],
    meta: { valueProp: 'Full-stack engineer with 10+ years experience...' }
  },
  sections: {
    sections: [
      { source: 'basics', render: 'header' },
      { source: 'meta.valueProp', title: 'Value Proposition' },
      { source: 'work', title: 'Experience' }
    ]
  }
});
```

#### Field templates

Field templates use LiquidJS syntax to customize how fields are rendered.

Available field templates:

- `location` - `{{ city }}{% if region %}, {{ region }}{% endif %}`
- `dateRange` - `{{ start | date: 'MMM YYYY' }} - {{ end | date: 'MMM YYYY' | default: 'Present' }}`
- `degree` - `{{ studyType }}{% if area %}, {{ area }}{% endif %}`
- `credential` - `{{ title | default: name }}{% if awarder %}, {{ awarder }}{% endif %}`
- `language` - `{{ language }}{% if fluency %} ({{ fluency }}){% endif %}`
- `skill` - `{{ name }}: {{ keywords | join: ', ' }}`
- `contactLine` - `{{ items | join: ' | ' }}`

Date format tokens:

- `YYYY`, `YY`, `MMMM`, `MMM`, `MM`, `M`, `DD`, `D`

Available filters:

- `date` - Format a date string
- `default` - Fallback for empty values
- `tenure` - Calculate duration
- `join` - Join array elements

Example: French resume

```ts
await client.callTool('pdf-resume', {
  filename: 'cv-francais.pdf',
  resume: { /* JSON Resume data */ },
  sections: {
    fieldTemplates: {
      dateRange: "{{ start | date: 'MM/YYYY' }} - {{ end | date: 'MM/YYYY' | default: 'Present' }}",
      location: '{{ city }}'
    }
  }
});
```

Example: verbose date format

```ts
await client.callTool('pdf-resume', {
  filename: 'resume.pdf',
  resume: { /* JSON Resume data */ },
  sections: {
    fieldTemplates: {
      dateRange: "{{ start | date: 'MMMM YYYY' }} to {{ end | date: 'MMMM YYYY' | default: 'Present' }}"
    }
  }
});
```

#### Two-column resume layout

```ts
await client.callTool('pdf-resume', {
  filename: 'two-column-resume.pdf',
  resume: {
    basics: {
      name: 'Jane Doe',
      label: 'Product Designer',
      email: 'jane@example.com'
    },
    work: [{
      name: 'Design Studio',
      position: 'Lead Designer',
      startDate: '2019-03',
      highlights: ['Redesigned product UI', 'Increased conversion by 25%']
    }],
    skills: [
      { name: 'Design', keywords: ['Figma', 'Sketch', 'Adobe XD'] },
      { name: 'Frontend', keywords: ['HTML', 'CSS', 'React'] }
    ],
    languages: [
      { language: 'English', fluency: 'Native' },
      { language: 'Spanish', fluency: 'Intermediate' }
    ]
  },
  layout: {
    style: 'two-column',
    gap: 30,
    columns: {
      left: { width: '30%', sections: ['skills', 'languages'] },
      right: { width: '70%', sections: ['work'] }
    }
  }
});
```

Layout options:

- `style` - "single-column" (default) or "two-column"
- `gap` - Space between columns in points (default: 30)
- `columns.left.width` - Left column width (percentage or points)
- `columns.left.sections` - Section source paths for left column
- `columns.right.width` - Right column width
- `columns.right.sections` - Section source paths for right column

### pdf-layout

Create a PDF with precise positioning and Yoga flexbox layout.

Parameters:

- `filename` (string, optional) - Filename for the PDF (defaults to "document.pdf")
- `title` (string, optional) - Document metadata
- `author` (string, optional) - Document metadata
- `pageSetup` (object, optional) - Page configuration
- `content` (array, required) - Content items
- `layout` (object, optional) - Layout options

Page setup:

```ts
pageSetup: {
  size: [612, 792],
  margins: { top: 72, bottom: 72, left: 72, right: 72 },
  backgroundColor: '#FFFFFF'
}
```

Content types:

Text and headings:

```ts
{
  type: 'text',
  text: 'Content here',
  fontSize: 12,
  bold: true,
  color: '#000000',
  align: 'left',
  x: 100,
  y: 200,
  oblique: 15,
  characterSpacing: 1,
  moveDown: 1,
  underline: true,
  strike: true
}
```

Shapes:

```ts
{ type: 'rect', x: 50, y: 50, width: 200, height: 100, fillColor: '#FF0000', strokeColor: '#000000', lineWidth: 2 }
{ type: 'circle', x: 300, y: 400, radius: 50, fillColor: '#00FF00', strokeColor: '#000000', lineWidth: 1 }
{ type: 'line', x1: 100, y1: 100, x2: 500, y2: 100, strokeColor: '#0000FF', lineWidth: 2 }
```

Images and pages:

```ts
{ type: 'image', imagePath: '/path/to/image.png', width: 200, height: 150, x: 100, y: 200 }
{ type: 'pageBreak' }
```

#### Flexbox layout engine

Use `type: 'group'` to create flexbox containers:

```ts
{
  type: 'group',
  direction: 'row',
  gap: 20,
  flex: 1,
  justify: 'center',
  alignItems: 'center',
  align: 'center',
  width: 300,
  height: 200,
  padding: 15,
  background: '#f5f5f5',
  border: { color: '#333', width: 1 },
  children: [
    { type: 'text', text: 'Child 1' },
    { type: 'text', text: 'Child 2' }
  ]
}
```

Common layout patterns:

Two equal columns:

```ts
{
  type: 'group',
  direction: 'row',
  gap: 20,
  children: [
    { type: 'group', flex: 1, children: [{ type: 'text', text: 'Left' }] },
    { type: 'group', flex: 1, children: [{ type: 'text', text: 'Right' }] }
  ]
}
```

Three columns with proportions (1:2:1):

```ts
{
  type: 'group',
  direction: 'row',
  gap: 15,
  children: [
    { type: 'group', flex: 1, children: [/* ... */] },
    { type: 'group', flex: 2, children: [/* ... */] },
    { type: 'group', flex: 1, children: [/* ... */] }
  ]
}
```

Centered card:

```ts
{
  type: 'group',
  width: 300,
  align: 'center',
  border: { color: '#333', width: 2 },
  padding: 20,
  children: [
    { type: 'heading', text: 'Card Title', align: 'center' },
    { type: 'text', text: 'Card content here' }
  ]
}
```

Space between items:

```ts
{
  type: 'group',
  direction: 'row',
  justify: 'space-between',
  children: [
    { type: 'text', text: 'Left' },
    { type: 'text', text: 'Right' }
  ]
}
```

Mixed positioning:

```ts
await client.callTool('pdf-layout', {
  layout: { overflow: 'auto' },
  content: [
    { type: 'heading', text: 'TITLE', x: 54, y: 50 },
    {
      type: 'group',
      direction: 'row',
      gap: 20,
      x: 54,
      y: 100,
      children: [
        { type: 'group', flex: 1, children: [/* ... */] },
        { type: 'group', flex: 1, children: [/* ... */] }
      ]
    },
    { type: 'text', text: 'Footer', x: 54, y: 700 }
  ]
});
```

Complete flyer example:

```ts
await client.callTool('pdf-layout', {
  pageSetup: { backgroundColor: '#fffef5' },
  content: [
    { type: 'heading', text: 'SUMMER FESTIVAL 2024', align: 'center', fontSize: 28, y: 50 },
    { type: 'text', text: 'July 15-17 | Central Park', align: 'center', y: 90 },
    {
      type: 'group',
      direction: 'row',
      gap: 20,
      x: 54,
      y: 130,
      children: [
        {
          type: 'group',
          flex: 1,
          border: { color: '#2196f3', width: 2 },
          padding: 15,
          children: [
            { type: 'heading', text: 'MUSIC', align: 'center', fontSize: 18 },
            { type: 'text', text: 'Live bands all weekend' },
            { type: 'text', text: '- Main Stage' },
            { type: 'text', text: '- Acoustic Tent' }
          ]
        },
        {
          type: 'group',
          flex: 1,
          border: { color: '#4caf50', width: 2 },
          padding: 15,
          children: [
            { type: 'heading', text: 'FOOD', align: 'center', fontSize: 18 },
            { type: 'text', text: '50+ local vendors' },
            { type: 'text', text: '- Food Court' },
            { type: 'text', text: '- Craft Beers' }
          ]
        }
      ]
    },
    {
      type: 'group',
      width: 300,
      align: 'center',
      y: 400,
      border: { color: '#ff9800', width: 2 },
      padding: 15,
      background: '#fff8e1',
      children: [
        { type: 'heading', text: 'TICKETS', align: 'center', fontSize: 16 },
        { type: 'text', text: 'Early Bird: $25', align: 'center' },
        { type: 'text', text: 'At Door: $35', align: 'center' }
      ]
    }
  ]
});
```

#### Emoji and Unicode support

Color emoji render as inline images. Unicode text is supported across major scripts.

```json
{
  "basics": {
    "name": "John Doe",
    "summary": "Developer passionate about clean code"
  }
}
```

### pdf-document

Create a flowing PDF document with automatic pagination.

### pdf-image

Render PDF pages to PNG images for previews or export.

### text-measure

Measure text width and height before layout.

## Tools

1. pdf-document
2. pdf-image
3. pdf-layout
4. pdf-resume
5. text-measure

## External resources

None.

## Prompts

1. resource-fetching

## Resources

- PDFKit Documentation
- JSON Resume Schema
- JSON Resume Editor

### Documentation

[API Docs](https://mcp-z.github.io/mcp-pdf)

More