@leafwright/mcp
The official Leafwright MCP server. It gives an AI
coding agent (Claude Code, Cursor, Codex, and any MCP client) the ability to
generate PDFs, build templates, and debug failed renders from their logs —
all through the Leafwright public API.
No headless Chrome, no Puppeteer in your bundle. The agent calls a tool, gets a
real signed PDF URL back.
Connect from claude.ai (remote, no install)
Leafwright also runs as a remote MCP server with OAuth. In claude.ai →
Settings → Connectors → Add custom connector, enter:
- Name: Leafwright
- Remote MCP server URL:
https://leafwright.co/mcp
Leave the OAuth fields empty — the connector registers itself and opens a
browser window where you sign in and pick an organization and default project.
Works with any MCP client that supports OAuth 2.1 + PKCE and Dynamic Client
Registration.
Install (local stdio)
Nothing to install — run it with npx:
npx -y @leafwright/mcp
Start the server without credentials, then call leafwright_login from your
agent. Open the returned verification URL, sign in, choose an organization and
default project, then call leafwright_auth_status.
Project API keys are still supported for server automation:
LEAFWRIGHT_API_KEY=lw_live_...
Get an account at leafwright.co.
Claude Code — install the plugin
/plugin marketplace add Tactic-Systems/leafwright-claude-plugin
/plugin install leafwright@leafwright
Connects to the hosted server, so there is nothing to install and Claude Code
handles the sign-in.
Configure your client
One-click:

From the command line:
claude mcp add --transport http leafwright https://leafwright.co/mcp
claude mcp add --transport stdio leafwright -- npx -y @leafwright/mcp
codex mcp add leafwright --url https://leafwright.co/mcp
codex mcp add leafwright -- npx -y @leafwright/mcp
By hand, Claude Code (~/.claude/mcp.json or project .mcp.json) and
Cursor (~/.cursor/mcp.json) share this shape:
{
"mcpServers": {
"leafwright": {
"command": "npx",
"args": ["-y", "@leafwright/mcp"],
"env": {}
}
}
}
Codex is the exception — it reads TOML from ~/.codex/config.toml, so the
JSON above will not work there:
[mcp_servers.leafwright]
command = "npx"
args = ["-y", "@leafwright/mcp"]
Restart the client. Before login, only auth/help tools appear; after browser
auth, the full leafwright_* tool set appears.
Environment
LEAFWRIGHT_API_KEY | no | — | Backward-compatible project API key (lw_live_… or lw_test_…). |
LEAFWRIGHT_MCP_TOKEN | no | — | MCP token (mcp_…) for non-interactive setups. |
LEAFWRIGHT_PROJECT_ID | no | selected project | Override the active default project. |
LEAFWRIGHT_MCP_READ_ONLY | no | false | true exposes only read tools — no renders, no template writes, no AI. |
Tools
Auth and context:
leafwright_login | Start browser login. |
leafwright_auth_status | Complete/check browser login. |
leafwright_logout | Revoke and clear local MCP auth. |
leafwright_list_organizations | List the selected token's organization. |
leafwright_list_projects | List projects in the selected organization. |
leafwright_select_project | Set the local active project. |
Read (available after auth, no side effects):
leafwright_list_templates | List the project's templates. |
leafwright_get_template | Fetch one template (draft HTML/CSS, sample data, versions). |
leafwright_validate_template | Validate a template / draft overrides before rendering. |
leafwright_get_job | Render job status and metadata. |
leafwright_get_job_logs | Render logs — failed assets, fonts, timeouts, overflow. |
leafwright_get_usage | Credits used/remaining for the billing period. |
leafwright_estimate_usage_cost | Estimate credits and overage cost for a planned batch of renders. |
Write (hidden when LEAFWRIGHT_MCP_READ_ONLY=true):
leafwright_render_html | Render raw HTML → PDF (signed URL). |
leafwright_render_url | Render a public URL → PDF (SSRF-protected). |
leafwright_render_template | Render a published template with JSON data. |
leafwright_create_template | Create a draft template. |
leafwright_update_template_draft | Update a draft's HTML/CSS/name/sample data. |
leafwright_ai_generate_template | Generate a draft template from a prompt. |
leafwright_ai_revise_template | Revise a draft from a natural-language instruction. |
leafwright_ai_fix_from_logs | Repair a template from a failed render's logs. |
HTML rules
Leafwright validates all HTML before rendering — the same rules apply to
leafwright_render_html, template create/update, and validation.
Supported
- Full documents: doctype,
<html>, <head>, <meta>, <title>, <body>,
and <style> blocks.
- Text, heading, list, table, and layout tags (
div, section, header,
footer, main, article, figure).
<img> with base64 data URIs (data:image/png, jpeg, gif, webp, or
svg+xml), relative paths, or cid: references.
class, style, id, standard layout/table/meta/image attributes, and
aria-* / data-*.
- Handlebars placeholders like
{{customer.name}} in templates.
Rejected
-
<script>, <iframe>, <object>, <embed>, <form>, <link>, and inline
event handlers.
-
Inline <svg> markup (svg, path, rect, g, and the rest of the SVG
element family). Encode the SVG as a base64 data URI and reference it
from an <img> instead — URL-encoded SVG data URIs are rejected:
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0i..." alt="Logo">
-
SVG in CSS url() backgrounds — use an <img> element instead.
-
External http(s) URLs in src attributes or CSS url() — the renderer never
fetches remote assets for HTML sources. Embed images as data URIs instead.
-
CSS @import.
Size limits: HTML 250 KB, CSS 120 KB, up to 200 pages per PDF. To render a
public web page with its remote assets, use leafwright_render_url, which
fetches the page behind SSRF protections.
Prompts
Ready-made workflows your client can invoke: create_invoice_template,
create_report_template, create_template_from_prompt, debug_pdf_layout,
explain_render_failure, integrate_nextjs, migrate_from_puppeteer.
Resources
leafwright://docs (API quickstart), leafwright://templates (your
templates), leafwright://usage (current usage), leafwright://jobs/recent
(the 20 most recent render jobs), leafwright://jobs/{jobId}/logs (logs for a
specific job).
The debugging loop
A code-only agent can't see its PDF. This server closes that loop:
- Agent renders a template → it fails or looks wrong.
- Agent calls
leafwright_get_job_logs → reads the real cause.
- Agent calls
leafwright_ai_fix_from_logs → gets a fix, re-renders, confirms.
Safety
The server only calls the Leafwright public API. It runs no shell commands from
agent input, stores MCP tokens in the OS keychain when possible, falls back to a
permission-restricted config file, and supports read-only mode. AI drafts
templates; publishing always requires a human in the dashboard.
Listed in the MCP registry
co.leafwright/leafwright in the
official MCP registry.
License
MIT · leafwright.co