Skip to main content
Glama

DocumentKit

English | 简体中文

Secure, high-throughput webpage-to-PDF and screenshot service for Node.js. DocumentKit exposes the same rendering core through a REST API, MCP Streamable HTTP, and MCP stdio.

Status: early development (0.x). APIs may change before 1.0.

Features

  • Render a URL or HTML string to PDF

  • Capture PNG, JPEG, or WebP screenshots

  • Memory-only output: generated documents are never persisted by DocumentKit

  • Reused Chromium process with isolated browser contexts per request

  • Bounded concurrency, queue backpressure, timeouts, and output limits

  • SSRF protection for navigations, redirects, and subresources

  • REST, MCP Streamable HTTP, and MCP stdio interfaces

  • OpenAPI documentation and Docker support

  • Reserved ArtifactStore interface for future disk or object-storage adapters

Related MCP server: Screenshot API

Requirements

  • Node.js 22 or newer

  • macOS or Linux supported by Playwright

The npm package downloads a compatible Chromium automatically, so no separate browser installation is normally required.

Install Node.js and Playwright

  1. Install Node.js 22 or newer from the Node.js download page or with a Node.js version manager, then verify the installation:

    node --version
    npm --version
  2. Install the project dependencies from the repository root:

    npm install

    This installs playwright-core and downloads the compatible Chromium build through @playwright/browser-chromium. Do not install Playwright globally.

  3. On Linux, install Chromium's operating-system dependencies if they are not already available:

    sudo npx playwright-core install-deps chromium

If browser downloading was disabled during npm install (for example, with PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1), download Chromium afterward with:

npx playwright-core install chromium

Quick start

npx --yes @crossdo/documentkit serve

The server listens on all interfaces (0.0.0.0:3000) by default. From the same machine, use:

  • REST: http://127.0.0.1:3000/v1

  • MCP: http://127.0.0.1:3000/mcp

  • OpenAPI UI: http://127.0.0.1:3000/docs

  • Health: http://127.0.0.1:3000/health/live

Deploy with PM2

Install DocumentKit locally, then use PM2 to keep it running:

mkdir -p ~/documentkit
cd ~/documentkit
npm init -y
npm install @crossdo/documentkit
npm install --global pm2
pm2 start ./node_modules/.bin/documentkit --name documentkit -- serve

Configure automatic startup after a server reboot. Run the command printed by pm2 startup, then save the current process list:

pm2 startup
pm2 save

Common operations:

pm2 status
pm2 logs documentkit
pm2 restart documentkit
pm2 stop documentkit

Update DocumentKit and restart it:

cd ~/documentkit
npm install @crossdo/documentkit@latest
pm2 restart documentkit
pm2 save

The service is network-accessible without authentication by default. Restrict port 3000 to trusted source addresses with a firewall or cloud security group. Configure DOCUMENTKIT_API_KEY when authentication is required.

Render HTML to PDF:

curl -sS http://127.0.0.1:3000/v1/pdf \
  -H 'content-type: application/json' \
  -d '{"html":"<!doctype html><h1>Hello from DocumentKit</h1>"}' \
  --output document.pdf

Capture a webpage screenshot:

curl -sS http://127.0.0.1:3000/v1/screenshots \
  -H 'content-type: application/json' \
  -d '{"url":"https://example.com","screenshot":{"fullPage":true}}' \
  --output screenshot.png

CLI

documentkit serve [--host 0.0.0.0] [--port 3000] [--api-key TOKEN]
documentkit mcp
documentkit doctor

For MCP stdio configuration:

{
  "mcpServers": {
    "documentkit": {
      "command": "npx",
      "args": ["--yes", "@crossdo/documentkit", "mcp"]
    }
  }
}

HTTP API

POST /v1/pdf

{
  "url": "https://example.com",
  "page": {
    "waitUntil": "load",
    "viewport": { "width": 1440, "height": 900, "deviceScaleFactor": 1 }
  },
  "pdf": {
    "format": "A4",
    "printBackground": true,
    "landscape": false
  }
}

POST /v1/screenshots

{
  "html": "<!doctype html><h1>Hello</h1>",
  "screenshot": {
    "type": "png",
    "fullPage": true,
    "scale": "css"
  }
}

Exactly one of url and html is required. Responses are raw binary data with Cache-Control: no-store. DocumentKit does not write generated output to disk.

See API documentation, MCP documentation, and configuration.

Security

DocumentKit listens on all interfaces without authentication by default. This is convenient for trusted private networks, but port 3000 must be restricted with a firewall or cloud security group. Set an API key to require bearer authentication:

DOCUMENTKIT_API_KEY='replace-with-at-least-16-random-characters' \
  npx --yes @crossdo/documentkit serve

Private, local, reserved, and link-local rendering targets remain blocked. An application-level URL filter cannot replace an operating-system or container egress firewall. Production deployments should deny private network destinations at the network layer as well. Read SECURITY.md and the security model before exposing the service.

Performance model

DocumentKit starts one Chromium process and reuses it. Each render receives a fresh, isolated browser context which is closed after completion. A bounded queue prevents unbounded memory growth:

  • concurrency: 4 jobs

  • waiting queue: 32 jobs

  • job timeout: 45 seconds

  • output limit: 25 MiB

  • MCP inline limit: 5 MiB

  • declared network budget: 50 MiB per page

Chromium disk and media caches are minimized. Application output remains in memory and is released after the response. Tune concurrency based on available RAM; Chromium-heavy jobs commonly need substantially more memory than their final PDF size.

Development

npm install
npm run check
npm run dev

See CONTRIBUTING.md.

License

MIT

Related MCP Connectors

Related MCP Servers