pscat as a tool for agents

Everything a coding agent — Claude Code, Codex, OpenClaw, Hermes, or anything else — needs to render, debug, and generate PostScript with pscat. Two integration surfaces, because agents differ: instruction files for agents that read docs, and an MCP server for agents that call tools.

Build once

git clone https://github.com/PSCatLabs/pscat
cd pscat
cargo build --release      # → target/release/pscat and target/release/pscat-mcp

Surface 1 — the docs path (skill)

skills/pscat/SKILL.md is a one-page tool reference: command recipes for rendering (PNG/SVG/PDF, page size, dpi, halftone), debugging (--headless, --pstack-on-error, exit codes), handwritten-note generation, typewritten pages, and the pitfalls, written for an installed pscat. Claude Code picks it up automatically as a skill; it's plain markdown, so any docs-reading agent can use it — AGENTS.md points there, which is where Codex looks first.

skills/psviz/SKILL.md is the paper-viz companion to pscat/psart: it teaches agents to reach for lib/graph.ps (plotfn/plotparam/plotpolar/plotsurface) and lib/dataviz.ps (bar/line/area/scatter/pie) for documents, with calling conventions and copy-paste templates — so a “make me a chart for my paper” request goes straight to a clean figure instead of the generative-art loop. The interactive counterpart lives at Charts.

Surface 2 — the MCP server

pscat-mcp speaks MCP over stdio and exposes four tools. It shells out to the pscat CLI (found next to it) rather than linking the interpreter — PostScript's = and print write to stdout, which is the JSON-RPC channel, so in-process execution could corrupt the protocol. The tools stay in lock-step with the CLI by construction.

ToolInOut
render_postscript source; optional width/height (points), dpi, format (png/svg/pdf), halftone, out_path PNG page images inline (or SVG text; PDF written to out_path). A program that errors still returns the partial render, with the error text alongside.
handwrite text; optional size, width, paper (plain/ruled), ink "r,g,b", jitter, seed, dpi, out_path a handwritten-note PNG — the /HandScript dynamic font, word-wrapped and auto-sized; same seed, same page
describe_art_capabilities none structured JSON listing the fonts, Type 3 faces, palettes, page templates and library procedures this build really has, so an agent need not guess names from documentation
eval_postscript source what the program printed; on error, the standard PostScript error name plus a gs-style operand-stack post-mortem

Registering it

# Claude Code
claude mcp add pscat -- pscat-mcp

# Codex
codex mcp add pscat -- pscat-mcp

(With a build from a checkout instead of an install, give the full path: $PWD/target/release/pscat-mcp.)

For OpenClaw, Hermes, or any other MCP client, the generic stdio config:

{ "mcpServers": { "pscat": { "command": "pscat-mcp", "args": ["--out-root", "/path/to/output"] } } }

The server needs only the two binaries side by side: the handwrite tool runs pscat handwrite, with no checkout or shell script.

Each call is bounded: a time limit (--timeout, default 60 s), capped input, output and inline image sizes, and out_path confined to the server's output root (its working directory, or --out-root DIR). It speaks MCP revisions 2025-11-25 and 2025-06-18. Limits, protocol and the use-case table: the agents guide; what the tools can still do: SECURITY.md.

The CLI, for direct shelling

pscat --png out.png file.ps              # render (also --svg / --pdf)
pscat --page 500x500 --dpi 300 ...       # canvas in points; dpi scales pixels
generate | pscat --png out.png -         # '-' reads the program from stdin
pscat --headless --pstack-on-error f.ps  # debug: error name + stack post-mortem
pscat -e '3 4 add ='                     # one-liner eval
pscat handwrite "note text"               # string → handwritten PNG

Exit code 0 means a clean run; nonzero means a PostScript error, named on stderr. --png writes the partial canvas even after an error — usually exactly what you want when debugging.

Working on pscat with an agent

The repo itself is agent-first: docs/dev/HANDOFF.md orients a fresh session and AGENTS.md holds the working conventions. See Contribute.