ProvenPin Install

pdfkit generate PDF: working versions (tested 2026-10-16)

Build a PDFDocument with pdfkit, stream it into a buffer, and assert the output starts with %PDF using only built-in fonts offline.

passed2 passed · 0 failed2026-10-16 02:18 UTC
Status
passed
Last passed
2026-10-16 02:18 UTC
Tests
2 / 2
Language
TypeScript
Runtime
node v22.23.3
pinned versions3
pdfkit@0.20.2@types/node@26.6.5tsx@4.23.15
run it
npm install --no-audit --no-fund --ignore-scripts=false
npm test
test environment
node v22.23.3
linux 6.17.0-1022-azure
x64
runner: github-actions 38839686104

The code

Exactly the files that passed. Your agent can pull them with get_recipe("pdfkit-generate-pdf") (install), or see them on GitHub.

package.json
{
  "name": "pdfkit-generate-pdf",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "node --import tsx --test test/*.test.ts"
  },
  "dependencies": {
    "pdfkit": "0.20.2"
  },
  "devDependencies": {
    "@types/node": "26.6.5",
    "tsx": "4.23.15"
  }
}
src/pdf.ts
import PDFDocument from "pdfkit";
import { PassThrough } from "node:stream";

export type Row = [string, string, string];

/**
 * Renders a small document (heading, paragraph, table-like rows) into a buffer.
 * Uses only pdfkit's built-in standard fonts, so no network access is required.
 */
export function generatePdf(title: string, body: string, rows: Row[]): Promise<Buffer> {
  return new Promise((resolve, reject) => {
    const doc = new PDFDocument({ size: "A4", margin: 50 });
    const stream = new PassThrough();
    const chunks: Buffer[] = [];

    stream.on("data", (chunk: Buffer) => chunks.push(chunk));
    stream.on("end", () => resolve(Buffer.concat(chunks)));
    stream.on("error", reject);

    doc.pipe(stream);

    doc.font("Helvetica-Bold").fontSize(20).text(title);
    doc.moveDown();
    doc.font("Helvetica").fontSize(11).text(body, { align: "justify" });
    doc.moveDown();

    const columns = [50, 260, 410];
    let y = doc.y;

    rows.forEach((row, index) => {
      doc.font(index === 0 ? "Helvetica-Bold" : "Helvetica").fontSize(11);
      doc.text(row[0], columns[0], y);
      doc.text(row[1], columns[1], y);
      doc.text(row[2], columns[2], y);
      y += 20;
      doc.moveTo(50, y - 6).lineTo(545, y - 6).stroke();
    });

    doc.end();
  });
}
test/pdf.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { generatePdf } from "../src/pdf.ts";

test("generates a PDF starting with %PDF and a non-trivial length", async () => {
  const pdf = await generatePdf(
    "Quarterly Report",
    "This document is produced entirely offline using pdfkit's built-in fonts.",
    [
      ["Region", "Units", "Revenue"],
      ["North", "120", "$4,800"],
      ["South", "95", "$3,700"],
      ["East", "140", "$5,600"],
    ],
  );

  assert.ok(Buffer.isBuffer(pdf));
  assert.equal(pdf.subarray(0, 5).toString("latin1"), "%PDF-");
  assert.ok(pdf.length > 500, `expected a non-trivial length, got ${pdf.length}`);
});

test("writes a valid EOF marker", async () => {
  const pdf = await generatePdf("Empty", "No rows here.", [["A", "B", "C"]]);
  assert.ok(pdf.subarray(0, 5).toString("latin1").startsWith("%PDF"));
  assert.ok(pdf.subarray(-1024).toString("latin1").includes("%%EOF"));
});

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.