npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pretext-pdf-mcp

v1.5.11

Published

MCP server: generate professional PDFs from JSON in Claude, Cursor, Windsurf, or any AI agent. Serverless, no Chromium. Invoices, reports, resumes.

Readme

pretext-pdf-mcp

npm version npm downloads license CI

MCP server for pretext-pdf — generate professional PDFs from structured JSON in Claude, Cursor, or any AI agent.

No headless browser. No puppeteer. Pure Node.js with embedded fonts and precision text layout.

Live Demo

▶ Open Live Demo — edit JSON, click Generate, see a real PDF in seconds. No install.

▶ Open in StackBlitz — fork and edit the playground code.

4 templates included: GST Invoice · Market Report · Resume/CV · Custom


Connect via Smithery

The fastest way — no install, works instantly in any MCP-compatible agent:

https://pretext-pdf.run.tools

Or add via CLI:

smithery mcp add himaan4149-kv55/pretext-pdf

Local Install (Claude Desktop / Cursor / Windsurf)

Option 1: npx (no global install needed)

npx pretext-pdf-mcp

Option 2: Global install

npm install -g pretext-pdf-mcp
pretext-pdf-mcp

Claude Desktop Configuration

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "pretext-pdf": {
      "command": "npx",
      "args": ["-y", "pretext-pdf-mcp"]
    }
  }
}

Config file location:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Using with Claude Code CLI

Option A — one-liner (user-scoped, persists across projects):

claude mcp add pretext-pdf-mcp -- npx -y pretext-pdf-mcp

Option B — project-scoped .mcp.json (checked into repo, shared with your team):

Create .mcp.json in your project root:

{
  "mcpServers": {
    "pretext-pdf": {
      "command": "npx",
      "args": ["-y", "pretext-pdf-mcp"]
    }
  }
}

Then restart Claude Code (or run /mcp to verify). All 6 tools are available in your session. Type /mcp to confirm the server appears.

HTTP Transport Mode (advanced)

By default the server runs over stdio (MCP standard transport). For HTTP transport:

MCP_TRANSPORT=http MCP_PORT=3000 npx pretext-pdf-mcp

Environment variables:

  • MCP_TRANSPORT — Set to http to enable HTTP transport (default: stdio)
  • MCP_PORT — HTTP listen port when MCP_TRANSPORT=http (default: 3000)
  • MCP_HOST — HTTP listen host (default: 127.0.0.1)

Security note: HTTP transport is intended for trusted local networks only. Do not expose the HTTP port to the public internet without adding an authentication layer.

Known Limitations

  • Italic fonts — Italic markdown (*text*) requires an italic font variant. Inter italic is supported via @fontsource/inter (installed automatically). For other fonts, provide { family, weight, style: 'italic', src } in doc.fonts.
  • QR codes, barcodes, charts — Require optional peer dependencies: qrcode, bwip-js, vega/vega-lite. Install the ones you need.
  • SVG and images — Image URLs must be HTTPS. Private/local IP addresses are blocked (SSRF prevention). File paths require absolute paths.
  • Large documents — No hard page limit, but generation time scales with page count. Documents over 10,000 content elements trigger a performance advisory.
  • CJS consumers — pretext-pdf is ESM-only. If your project uses CommonJS, use dynamic import().

Tools

| Tool | Input | Output | |------|-------|--------| | generate_pdf | PdfDocument JSON descriptor | Base64 PDF + filename + size | | generate_invoice | Invoice data (parties, items, GST, currency) | Base64 PDF | | generate_report | Report sections with optional tables and callouts | Base64 PDF | | generate_from_markdown | Markdown string | Base64 PDF | | validate_document | PdfDocument JSON | Validation result (valid/errors) | | list_element_types | none | Markdown reference of all element types |

generate_pdf

Full-power access to the pretext-pdf API. Pass any PdfDocument descriptor.

{
  "document": {
    "pageSize": "A4",
    "footer": { "text": "Page {{pageNumber}} of {{totalPages}}", "fontSize": 9 },
    "content": [
      { "type": "heading", "level": 1, "text": "My Document" },
      { "type": "paragraph", "text": "Hello world." }
    ]
  },
  "filename": "my-document"
}

Returns:

{
  "success": true,
  "base64": "<base64-encoded PDF bytes>",
  "filename": "my-document.pdf",
  "size_bytes": 42816
}

generate_invoice

Business-friendly invoice generator. No PDF knowledge needed.

{
  "from": {
    "company": "Antigravity Systems",
    "address": "Gurugram, Haryana",
    "gstin": "06AABCA1234Z1ZK",
    "email": "[email protected]"
  },
  "to": {
    "company": "TCS Ltd",
    "address": "Mumbai, Maharashtra",
    "gstin": "27AAACT2727Q1ZW"
  },
  "invoice_number": "INV-2026-001",
  "date": "2026-04-08",
  "due_date": "2026-05-08",
  "currency": "INR",
  "items": [
    {
      "description": "LLM Fine-tuning Pipeline",
      "hsn_code": "998314",
      "quantity": 1,
      "rate": 250000,
      "gst_rate": 18
    },
    {
      "description": "AI Strategy Workshop",
      "quantity": 2,
      "rate": 75000,
      "gst_rate": 18
    }
  ],
  "notes": "Payment due within 30 days. NEFT/IMPS preferred."
}

Returns:

{
  "success": true,
  "base64": "<base64-encoded PDF bytes>",
  "filename": "invoice-INV-2026-001.pdf",
  "size_bytes": 68420
}

Features:

  • Supports INR, USD, EUR, GBP
  • Auto-calculates IGST per line item when gst_rate is set
  • HSN/SAC code column appears automatically when any item has it
  • Company header with from/to details in a 2-column table
  • Professional footer with invoice number and page numbers

generate_report

Multi-section report with optional TOC, tables, and callout boxes.

{
  "title": "Haryana Real Estate Q1 2026",
  "subtitle": "Residential & Commercial Analysis",
  "author": "Antigravity Research",
  "include_toc": true,
  "sections": [
    {
      "heading": "Executive Summary",
      "body": "Strong growth across all micro-markets.\n\nGurugram led with 18% YoY volume growth.",
      "table": {
        "headers": ["Market", "Avg Rs./sqft", "YoY"],
        "rows": [
          ["New Gurugram", "9,800", "+15.6%"],
          ["Sohna Road", "8,400", "+12.1%"]
        ]
      },
      "callout": {
        "style": "warning",
        "text": "Repo rate risk: any hike above 6.75% could suppress volumes 10-15%."
      }
    }
  ]
}

list_element_types

No input. Returns a markdown reference of all 22 element types (paragraph, heading, table, list, image, svg, code, blockquote, callout, toc, form-field, comment, hr, spacer, page-break, rich-paragraph, qr-code, barcode, chart, footnote-def, float-group, and toc-entry) with key properties and examples.

generate_from_markdown

Convert a Markdown string to a PDF without writing any JSON. Supports headings, bold/italic, strikethrough, inline code, links, ordered/unordered lists (up to 3 levels), GFM tables (with column alignment), GFM task lists (☑/☐), blockquotes, fenced code blocks, and horizontal rules. Note: code blocks render as plain indented text — not styled monospace. For styled code blocks or richer layouts, use generate_pdf.

{
  "markdown": "# Hello\n\nThis is a **bold** paragraph.\n\n- Item 1\n- Item 2",
  "filename": "hello",
  "page_size": "A4",
  "font_size": 12
}

Returns:

{
  "success": true,
  "base64": "<base64-encoded PDF bytes>",
  "filename": "hello.pdf",
  "size_bytes": 18432
}

Limits: markdown max 100,000 characters. font_size must be 6–144. page_size one of: A4, Letter, Legal. Default filename: document.

validate_document

Validate a pretext-pdf document schema without rendering it. Use this as a cheap preflight check before calling generate_pdf — catches typos, missing required fields, and unknown props in strict mode.

{
  "document": {
    "pageSize": "A4",
    "content": [{ "type": "heading", "level": 1, "text": "Test" }]
  },
  "strict": true
}

Valid response:

{ "valid": true, "error_count": 0, "warning_count": 0, "errors": [], "warnings": [] }

Invalid response:

{
  "valid": false,
  "error_count": 2,
  "warning_count": 0,
  "errors": [
    {
      "path": "doc.content[0].colour",
      "message": "unknown property. did you mean \"color\"",
      "code": "UNKNOWN_PROPERTY",
      "severity": "error",
      "unknownProp": "colour",
      "suggestion": "color"
    },
    {
      "path": "doc.pageSize",
      "message": "unknown property. did you mean \"pageSize\"",
      "code": "UNKNOWN_PROPERTY",
      "severity": "error",
      "unknownProp": "pageSise",
      "suggestion": "pageSize"
    }
  ],
  "warnings": []
}

Tip: Pass strict: true to catch misspelled props with Levenshtein-nearest suggestions. Default is strict: false — only checks required fields and types.

Decoding the base64 PDF

In Node.js:

const bytes = Buffer.from(result.base64, 'base64')
fs.writeFileSync('output.pdf', bytes)

In TypeScript (browser):

const bytes = Uint8Array.from(atob(result.base64), c => c.charCodeAt(0))
const blob = new Blob([bytes], { type: 'application/pdf' })

In Python:

import base64
pdf_bytes = base64.b64decode(result['base64'])
with open('output.pdf', 'wb') as f:
    f.write(pdf_bytes)

License

MIT — Himanshu Jain