Skip to main content
Glama
gian-reto

print-blocks

by gian-reto

print-blocks

print-blocks is a small TypeScript service that prints structured documents to ESC/POS thermal printers.

It has an API endpoint /print that accepts a JSON payload describing a document as an array of blocks, renders them to ESC/POS bytes with react-thermal-printer, and submits the resulting bytes to a CUPS printer with lp.

The service has no UI. It exposes:

  • POST /print for authenticated print jobs.

  • GET /healthz for unauthenticated liveness checks.

  • GET /openapi.json for generated OpenAPI JSON.

  • GET /docs for an interactive Scalar API reference when EXPOSE_DOCS=true.

  • GET /llms.txt for LLM-friendly Markdown API documentation when EXPOSE_LLMS_TXT=true.

  • ALL /mcp for authenticated MCP clients when EXPOSE_MCP=true.

Requirements

  • Node.js 24 and pnpm 10 for local development.

  • CUPS configured on the host.

  • A CUPS printer queue that accepts raw/native ESC/POS data.

  • The CUPS client command lp available wherever the app runs.

The production container installs cups-client, so lp is available inside the image.

Related MCP server: MCPOSprint

Configuration

Copy the example environment file and edit it:

cp .env.example .env

Note:

  • Documentation endpoints are disabled by default. Set EXPOSE_DOCS=true to enable /docs and EXPOSE_LLMS_TXT=true to enable /llms.txt.

  • The MCP endpoint is disabled by default. Set EXPOSE_MCP=true and provide a separate MCP_TOKEN with at least 32 characters to enable /mcp.

  • PRINTER_WIDTH configures the printer text width in characters and defaults to 48. PRINTER_DOT_WIDTH configures the raster width used for image-like blocks and defaults to 576 dots. Set it explicitly when your printer mode uses a different raster width, such as 384 dots.

  • Image blocks accept base64-encoded data through the data property. Supported image formats are JPEG, PNG, WebP, and SVG. Remote image URLs are disabled by default. Set ALLOW_REMOTE_IMAGE_URLS=true to allow image blocks to use an HTTPS url instead. Remote image fetching is intentionally strict: only HTTPS URLs with public domain hostnames are accepted, direct IP addresses and credentials are rejected, redirects are not followed, downloaded bytes are limited by MAX_REMOTE_IMAGE_BYTES, fetches time out after REMOTE_IMAGE_TIMEOUT_MS, and decoded image input is limited by MAX_IMAGE_INPUT_PIXELS. These restrictions are in place to prevent abuse and security issues, but enabling remote image URLs is only recommended in trusted environments.

Development

Install dependencies:

pnpm install

Run the dev server:

pnpm dev

SVG-backed block previews are available in development at:

http://localhost:3000/preview

Run checks:

pnpm typecheck
pnpm lint
pnpm format:check
pnpm test
pnpm build

API

POST /print

Headers:

Content-Type: application/json
Authorization: Bearer <API_TOKEN>

Body:

{
  "blocks": [
    {
      "type": "text",
      "content": "Hello from print-blocks",
      "align": "center",
      "bold": true
    }
  ]
}

Success response:

{
  "ok": true
}

GET /healthz

Returns:

{
  "ok": true
}

GET /openapi.json

Returns the OpenAPI specification for the API.

GET /docs

Returns an interactive API reference backed by Scalar and /openapi.json. This endpoint is only registered when EXPOSE_DOCS=true.

GET /llms.txt

Returns Markdown API documentation generated from the OpenAPI specification. This endpoint is only registered when EXPOSE_LLMS_TXT=true.

ALL /mcp

Serves a stateless MCP server over streamable HTTP. This endpoint is only registered when EXPOSE_MCP=true and requires Authorization: Bearer <MCP_TOKEN>.

Available tools:

  • get_info returns printer settings, service limits, supported blocks, and templates.

  • print renders print instructions and submits them to the configured printer.

  • list_templates lists examplary print templates that can be used as starting points or inspiration for print requests.

  • get_template returns Markdown instructions and the template's JSON structure for a given template id.

Manual smoke test

After the app is running:

curl -X POST "http://localhost:3000/print" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $API_TOKEN" \
  --data '{"blocks":[{"type":"text","content":"Hello from print-blocks","align":"center"}]}'

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Enables AI assistants to print documents, manage print queues, and control printers on macOS/Linux systems via the CUPS printing system. Supports printing PDFs, text files, and other formats with options like duplex printing, landscape orientation, and multiple copies.
    6
    8 npm
    12
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    An MCP server that enables users to print markdown tasklists, Notion tasks with QR codes, and arbitrary images directly to ESC/POS thermal printers over USB. It includes specialized tools for task processing, automated card generation, and printer diagnostics.
    7
    1
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    MCP server for printing POS receipts via CUPS printers, supporting a two-step confirmation flow with preview.
    1
    8 npm
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables generating print-ready PDFs from Markdown and submitting them to CUPS printers. Supports local, Tailscale, and Cloudflare Tunnel access.
    -