io.github.mcp-z/mcp-pdf

平台与服务

by mcp-z

用于创意 PDF 生成的 MCP 服务器,完整支持 emoji、Unicode,并可在离线环境中使用。

什么是 io.github.mcp-z/mcp-pdf

用于创意 PDF 生成的 MCP 服务器,完整支持 emoji、Unicode,并可在离线环境中使用。

README

@mcp-z/mcp-pdf

Docs: https://mcp-z.github.io/mcp-pdf PDF generation MCP server for documents, layouts, and image export.

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

常见问题

io.github.mcp-z/mcp-pdf 是什么?

用于创意 PDF 生成的 MCP 服务器,完整支持 emoji、Unicode,并可在离线环境中使用。

相关 Skills

Slack动图

by anthropics

Universal
热门

面向Slack的动图制作Skill,内置emoji/消息GIF的尺寸、帧率和色彩约束、校验与优化流程,适合把创意或上传图片快速做成可直接发送的Slack动画。

帮你快速做出适配 Slack 的动图,内置约束规则和校验工具,少踩上传与播放坑,做表情包和演示都更省心。

平台与服务
未扫描165.3k

MCP构建

by anthropics

Universal
热门

聚焦高质量 MCP Server 开发,覆盖协议研究、工具设计、错误处理与传输选型,适合用 FastMCP 或 MCP SDK 对接外部 API、封装服务能力。

想让 LLM 稳定调用外部 API,就用 MCP构建:从 Python 到 Node 都有成熟指引,帮你更快做出高质量 MCP 服务器。

平台与服务
未扫描165.3k

接口测试套件

by alirezarezvani

Universal
热门

扫描 Next.js、Express、FastAPI、Django REST 的 API 路由,自动生成覆盖鉴权、参数校验、错误码、分页、上传与限流场景的 Vitest 或 Pytest 测试套件。

帮你把API与集成测试自动化跑顺,减少回归漏测;能力全面,尤其适合复杂接口场景的QA团队。

平台与服务
未扫描23.5k

相关 MCP Server

Slack 消息

编辑精选

by Anthropic

热门

Slack 是让 AI 助手直接读写你的 Slack 频道和消息的 MCP 服务器。

这个服务器解决了团队协作中需要 AI 实时获取 Slack 信息的痛点,特别适合开发团队让 Claude 帮忙汇总频道讨论或发送通知。不过,它目前只是参考实现,文档有限,不建议在生产环境直接使用——更适合开发者学习 MCP 如何集成第三方服务。

平台与服务
89.1k

by netdata

热门

io.github.netdata/mcp-server 是让 AI 助手实时监控服务器指标和日志的 MCP 服务器。

这个工具解决了运维人员需要手动检查系统状态的痛点,最适合 DevOps 团队让 Claude 自动分析性能数据。不过,它依赖 NetData 的现有部署,如果你没用过这个监控平台,得先花时间配置。

平台与服务
79.9k

by d4vinci

热门

Scrapling MCP Server 是专为现代网页设计的智能爬虫工具,支持绕过 Cloudflare 等反爬机制。

这个工具解决了爬取动态网页和反爬网站时的头疼问题,特别适合需要批量采集电商价格或新闻数据的开发者。不过,它依赖外部浏览器引擎,资源消耗较大,不适合轻量级任务。

平台与服务
71.9k

评论