Give Claude Code a PDF tool
Claude Code can write you a PDF generator. It is faster to give it one. Connecting the Galley MCP server takes one command, needs no account, and ends with Claude producing real files instead of HTML it hopes you will print.
Connect
Section titled “Connect”claude mcp add --transport http galley https://mcp.galleyrender.com/mcpThat is the whole setup. No API key, no signup. Restart Claude Code (or start a new session) and check:
claude mcp listgalley: https://mcp.galleyrender.com/mcp (HTTP) - ✓ ConnectedTen tools appear: list_templates, get_template, create_template, update_template, validate_data, render, get_render, list_renders, usage and create_account. Only render costs anything.
The transport is stateless streamable HTTP, so there is no session to keep alive and nothing to restart when your laptop sleeps. Any instance answers any request.
The first call, keyless
Section titled “The first call, keyless”The first render with no key mints a 50-render trial and returns its token in the response. The trial is a real account: it holds templates, renders and usage like any other, and it comes with the twenty-two-template starter library already loaded.
Ask for something:
Make me a PDF invoice for Acme Robotics — one line for the September Starter plan at $19, one for 3,200 renders of overage at $4 each, 7% tax, invoice number INV-1042, due in 30 days.
Claude does not guess at the payload. It reads the contract first.
● galley - list_templates (MCP) ⎿ 22 templates: invoice, quote, change-order, receipt, statement, purchase-order, certificate, report-cover, report-table, shipping-label, packing-slip, og-card, quote-card, event-ticket, badge, menu, price-sheet, letterhead, chart-card, summary, slide-deck, slide
● galley - get_template (MCP) ⎿ invoice@1 — Letter-size invoice with line items, totals, and payment terms. Required: invoice_number, issued_on, seller, buyer, line_items. line_items[].quantity: number. line_items[].unit_price: number. tax_rate: number, 0–1.
● galley - render (MCP) ⎿ { "object": "render", "id": "rnd_7hq2m4x8k1bv", "status": "succeeded", "template": "invoice@1", "format": "pdf", "cached": false, "url": "https://<account>.r2.cloudflarestorage.com/galley-renders/renders/…?X-Amz-Expires=3600&X-Amz-Signature=…", "page_count": 1, "billable_units": 1, "trial": { "mode": "keyless_trial", "renders_limit": 50, "renders_remaining": 49, "trial_token": "glr_sk_…" } }
● Invoice INV-1042 is rendered — one page, $34.03 total after 7% tax. Download: https://<account>.r2.cloudflarestorage.com/galley-renders/renders/… That used 1 of your 50 trial renders.Three tool calls, in the order the server’s instructions recommend: see what exists, read the schema, render. Claude reaches for validate_data instead of render when it is assembling a payload from a file it does not trust — that call is free and returns the same field-level errors a render would.
Keep the same trial
Section titled “Keep the same trial”Claude Code does not persist the trial token for you. Without a key, the trial identity is derived from a salted hash of your IP and user agent, which survives a session but not a coffee-shop move. If you want the same trial across networks, tell Claude to save the trial_token it got back and add it as a header:
claude mcp remove galleyclaude mcp add --transport http galley https://mcp.galleyrender.com/mcp \ --header "X-Galley-Api-Key: glr_sk_…"A trial token works as an ordinary API key — against this MCP server and against https://api.galleyrender.com too.
Add a real key
Section titled “Add a real key”When 50 renders is not enough, ask Claude in-session:
Create a Galley account for matt@example.com.
It calls create_account, a verification link is emailed, and the tool returns status: "pending_verification". Click the link, then ask Claude to call it again with the same address — it returns the API key once. The trial is upgraded in place, so the templates and renders you made during it are kept.
Store the key and re-add the server with the header:
claude mcp remove galleyclaude mcp add --transport http galley https://mcp.galleyrender.com/mcp \ --header "X-Galley-Api-Key: $GALLEY_API_KEY"The free tier on a real account is 200 renders a month. Beyond that it is $0.006 per PNG and $0.015 per PDF page, or a plan — pricing has the detail. Cache hits are never billed, which matters more than it sounds: Claude re-running the same render while iterating on a document costs nothing after the first.
Share it with the team
Section titled “Share it with the team”The default scope is local to you. --scope project writes a .mcp.json at the repo root, which you commit:
claude mcp add --scope project --transport http galley https://mcp.galleyrender.com/mcp{ "mcpServers": { "galley": { "type": "http", "url": "https://mcp.galleyrender.com/mcp", "headers": { "X-Galley-Api-Key": "${GALLEY_API_KEY}" } } }}${GALLEY_API_KEY} is expanded from the environment when Claude Code loads the file, so the secret never enters the repository. Anyone who clones and has the variable set gets the tools; anyone without it lands on the keyless trial and can still render fifty documents. Claude Code prompts each person once to approve a project-scoped server before it will use it.
Document the variable in your README next to whatever else the project needs:
GALLEY_API_KEY=glr_sk_… # https://galleyrender.com/docs/quickstartInstall the skill file
Section titled “Install the skill file”The MCP tool descriptions tell Claude what each tool does. The skill file tells it how the product fits together — when to prefer satori over chromium, why to pin a template version, that an expired URL should be re-signed rather than re-rendered, and the full error table. It is one page, written for a model.
mkdir -p .claude/skills/galley-rendercurl -sS https://galleyrender.com/skill.md -o .claude/skills/galley-render/SKILL.mdThe file already carries the frontmatter Claude Code expects — name: galley-render and a description that says when to reach for it — so there is nothing to edit. Commit it alongside .mcp.json. The same file is served from https://mcp.galleyrender.com/skill.md, and https://galleyrender.com/llms.txt maps the rest of the documentation for a model that arrives by URL.
Put it in ~/.claude/skills/galley-render/SKILL.md instead if you want it everywhere rather than in one repo.
What it is good for
Section titled “What it is good for”Ordinary requests in a normal session:
Turn
reports/q3.jsoninto a PDF using the report-table template, landscape A4.
Render OG cards for every post in
content/blog/— title and description from the frontmatter, 1200×630 PNG.
The certificate we generated last week has the wrong inspection date. Fix it and re-render.
The last one is worth watching. Claude fixes the data and calls render again; because the payload changed, it is a new render. Ask for the same certificate twice and the second call comes back cached: true, free and instant.
When nothing in the library fits, Claude will write a template: create_template with one self-contained HTML document, inline CSS, Liquid expressions and a JSON Schema for the data. Ask it to include the schema — that is what turns a bad payload into a field-level error instead of a blank page.
When it does not connect
Section titled “When it does not connect”claude mcp list showing a failure is almost always one of three things.
✗ Failed to connect— check the URL has the/mcppath on the end.https://mcp.galleyrender.comalone serves a landing document, not the JSON-RPC endpoint.- Tools appear but every call returns
authentication_error— the header value is malformed. It isX-Galley-Api-Key: glr_sk_…, orAuthorization: Bearer glr_sk_…. A bearer token that is not a Galley key is ignored rather than forwarded, so an unrelated OAuth token in your environment quietly lands you on the trial instead of erroring. quota_exceededon a render — the 50 trial renders are spent. Callcreate_account, or add a key from an existing account.
What next
Section titled “What next”- What the MCP server is — the ten tools and the trial in detail.
- Give an OpenAI Agents SDK agent a PDF tool — the same server from Python.
- Skill file and llms.txt — what is in the skill file and why.