# @copperline/rendex-mcp
[](https://www.npmjs.com/package/@copperline/rendex-mcp)
[](https://www.npmjs.com/package/@copperline/rendex-mcp)
[](https://opensource.org/licenses/MIT)
[](https://lobehub.com/mcp/copperline-labs-rendex-mcp)
MCP server for [Rendex](https://rendex.dev) — render raw HTML, Markdown, or any URL to an image or PDF via AI agents using the Model Context Protocol.
## Quick Start
### Claude Desktop / Cursor / Windsurf (npx)
Add to your MCP client config:
```json
{
"mcpServers": {
"rendex": {
"command": "npx",
"args": ["-y", "@copperline/rendex-mcp"],
"env": {
"RENDEX_API_KEY": "your-api-key"
}
}
}
}
```
**Where to add this:**
| Client | Config location |
|--------|----------------|
| Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) |
| Cursor | `.cursor/mcp.json` in project root, or Settings > MCP |
| Windsurf | Settings > MCP Servers |
### Claude Code (CLI)
Add a `.mcp.json` to your project root with the same config above. Then restart Claude Code.
> **Important**: Add `.mcp.json` to your `.gitignore` — it contains your API key.
### Remote (zero-install, OAuth or API key)
Connect to the hosted server at `https://mcp.rendex.dev/mcp` — no install needed.
It's fronted by **OAuth 2.1** (authorization-code + PKCE S256), so OAuth-capable
clients (ChatGPT, Claude, Cursor, the MCP Inspector) connect with **no API key** —
you sign in with a one-time email code and each caller bills against their own
Rendex plan and credit pool.
Clients that prefer a static key can still pass one directly:
```json
{
"mcpServers": {
"rendex": {
"url": "https://mcp.rendex.dev/mcp",
"headers": {
"Authorization": "Bearer your-api-key"
}
}
}
}
```
## Tools
### `rendex_screenshot`
Render any webpage, raw HTML, or Markdown to an image or PDF.
```
"Take a screenshot of https://example.com"
"Capture the full page of https://news.ycombinator.com in dark mode"
"Generate a PDF of https://github.com with A4 page size"
"Capture https://amazon.de as seen from Germany"
"Render this HTML invoice as a PDF"
"Render this Markdown release note as a PDF"
```
**Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `url` | string | required* | Webpage URL to capture. Mutually exclusive with `html` and `markdown`. |
| `html` | string | — | Raw HTML to render. Mutually exclusive with `url` and `markdown`. |
| `markdown` | string | — | Markdown to render (server converts to HTML). Mutually exclusive with `url` and `html`. |
| `data` | object | — | Key-value data for Mustache templating. When set, the `html` or `markdown` string is rendered as a logic-less Mustache template before capture. Invalid with `url`. |
| `format` | `"png"` \| `"jpeg"` \| `"webp"` \| `"pdf"` | `"png"` | Output format |
| `fullPage` | boolean | `false` | Capture full scrollable page |
| `darkMode` | boolean | `false` | Emulate dark color scheme |
| `width` | number | `1280` | Viewport width (320-3840) |
| `height` | number | `800` | Viewport height (240-2160) |
| `resizeWidth` | number | — | Downscale output to this width in px (aspect ratio preserved if `resizeHeight` omitted). Ignored for PDF |
| `resizeHeight` | number | — | Downscale output to this height in px (aspect ratio preserved if `resizeWidth` omitted). Ignored for PDF |
| `quality` | number | `80` | Image quality 1-100 (JPEG/WebP only, default 80) |
| `delay` | number | `0` | Wait ms before capture |
| `blockAds` | boolean | `true` | Block ads and trackers |
| `blockCookieBanners` | boolean | — | Hide common cookie/consent banners (GDPR/CCPA) before capture |
| `blockResourceTypes` | string[] | — | Block resource types: `font`, `image`, `media`, `stylesheet`, `other` |
| `device` | string | — | Device preset: `desktop`, `iphone_15`, `iphone_se`, `pixel_8`, `ipad`, `ipad_pro` — sets viewport, scale, and user agent in one shot. Overrides `width`/`height`/`deviceScaleFactor`/`userAgent` |
| `deviceScaleFactor` | number | `2` | Device pixel ratio (1-3). 2× Retina by default |
| `timeout` | number | `30` | Max seconds to wait for page load (5-60) |
| `waitUntil` | string | `"networkidle2"` | Page readiness: `load`, `domcontentloaded`, `networkidle0`, `networkidle2` |
| `waitForSelector` | string | — | CSS selector to wait for before capture |
| `bestAttempt` | boolean | `true` | Return partial render on timeout instead of failing |
| `selector` | string | — | CSS selector of element to capture instead of full page |
| `hideSelectors` | string[] | — | CSS selectors to hide (`display:none`) before capture, e.g. `['.modal', '#newsletter-popup']`. Max 50 |
| `css` | string | — | Custom CSS to inject before capture (max 50KB) |
| `js` | string | — | Custom JavaScript to execute before capture (max 50KB) |
| `cookies` | array | — | Cookies to set for authenticated captures (max 50) |
| `headers` | object | — | Custom HTTP headers for the page request |
| `userAgent` | string | — | Override browser user agent string |
| `pdfFormat` | string | — | PDF page size: `A4`, `Letter`, `Legal`, `Tabloid`, `A3` |
| `pdfLandscape` | boolean | — | PDF landscape orientation |
| `pdfPrintBackground` | boolean | `true` | Print background in PDF |
| `pdfScale` | number | `1` | PDF scale factor (0.1-2) |
| `pdfMargin` | object | — | PDF margins: `{top, right, bottom, left}` as CSS values |
| `geo` | string | — | ISO country code for geo-targeted capture (Pro/Enterprise) |
| `geoCity` | string | — | City for geo-targeting (requires `geo`) |
| `geoState` | string | — | State for geo-targeting (requires `geo`) |
| `async` | boolean | — | Process asynchronously (returns job ID) |
| `webhookUrl` | string | — | URL to receive callback when async capture completes |
| `cacheTtl` | number | — | Seconds to cache result (3600-2592000) |
### `rendex_extract`
Extract clean reader-mode content from any webpage as Markdown, JSON, or HTML. Runs the same Chromium render pass as a screenshot, so it captures content **after JavaScript runs** — handling SPAs that fetch-only readers miss. Strips nav, ads, and boilerplate, returning the article body plus title, byline, and excerpt. Great for feeding page content to an LLM, summarization, or RAG ingestion.
```
"Extract the article text from https://example.com/post as Markdown"
"Pull the readable content from this SPA as JSON so I can summarize it"
```
**Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `url` | string | required | Webpage URL to extract readable content from |
| `extractFormat` | `"markdown"` \| `"json"` \| `"html"` | `"markdown"` | Output shape — `markdown` (LLM-friendly prose), `json` (structured: title/byline/excerpt/siteName/length), or `html` (cleaned reader-mode HTML) |
| `device` | string | — | Device preset (`desktop`, `iphone_15`, `iphone_se`, `pixel_8`, `ipad`, `ipad_pro`) — extract the mobile/tablet version of a page |
| `blockAds` | boolean | `true` | Block ads and trackers before extraction |
| `blockCookieBanners` | boolean | — | Hide common cookie/consent walls before extraction |
| `hideSelectors` | string[] | — | CSS selectors to hide before extraction, e.g. `['.modal', '#newsletter-popup']`. Max 50 |
| `waitUntil` | string | `"networkidle2"` | Page readiness: `load`, `domcontentloaded`, `networkidle0`, `networkidle2` |
| `timeout` | number | `30` | Max seconds to wait for page load (5-60) |
### `rendex_render_link`
Render a URL, raw HTML, or Markdown and get back a **signed, hosted, edge-cached image URL** instead of the bytes — ideal for dynamic OG images. Drop the URL into `` or an `
` tag and Rendex serves a cached copy on every share. Takes the **same parameters as `rendex_screenshot`**, plus an optional `expiresIn`. Returns `{ url, expiresAt, format, cacheTtl }`.
```
"Make me a hosted OG-image URL for this Markdown release note"
"Give me a render link for this HTML card that I can drop into og:image"
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| *(all `rendex_screenshot` params)* | — | — | Same source (`url`/`html`/`markdown`), format, sizing, and templating options |
| `expiresIn` | number | server TTL | Seconds until the signed URL expires (60–2592000) |
### `render_artifact`
Turn Markdown or HTML into a **branded, downloadable artifact — a PDF, a PNG, and a hosted share page — in one call**. Ideal for agent outputs: reports, invoices, summaries, release notes, dashboards. Apply a logo, accent color, font, header, and footer; choose PDF page size/orientation/margins. Returns hosted URLs `{ pdfUrl, pngUrl, shareUrl, expiresAt }` — no storage needed on your side. **Each requested format costs 1 render credit.**
```
"Turn this Markdown report into a branded PDF and PNG with our logo and an orange accent"
"Render this invoice HTML to a PDF and give me a share link that expires in a week"
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `content` | string | required | The Markdown or HTML body to render (up to ~4MB) |
| `inputFormat` | `"markdown"` \| `"html"` | `"markdown"` | How to interpret `content` — `markdown` is converted to styled HTML; `html` is used as a body fragment |
| `formats` | `("pdf" \| "png")[]` | `["pdf","png"]` | Which formats to produce. Each costs 1 credit |
| `accentColor` | string | — | CSS accent color for the bar, links, and headings (e.g. `#EA580C`) |
| `logo` | string | — | http(s) URL of a logo image shown in the header |
| `header` | string | — | plain-text header line shown beside the logo |
| `footer` | string | — | plain-text footer line shown at the bottom |
| `font` | string | — | CSS font-family stack for the body |
| `pageSetup` | object | — | `{ size, orientation, margin{top,right,bottom,left}, scale, width, height, fullPage }` |
| `data` | object | — | Mustache data — when set, `content` is rendered as a logic-less Mustache template (plus `{{logo}}`/`{{header}}`/… from `branding`) before conversion |
| `expiresIn` | number | `86400` | Seconds until the hosted URLs expire (3600–2592000). Default 24h |
### Rendex Watch
Monitor a URL on a schedule and get notified when it changes — real-Chrome **visual diff** (with a highlighted overlay), an extracted-**text** diff, or **both**. Eight tools let an agent set up, inspect, edit, and tear down watches on the shared Rendex platform (one `rdx_` key, one credit pool).
```
"Watch https://example.com/pricing for visual changes and alert my webhook"
"Before I save it, test whether you can capture #pricing on that page"
"Show me the last few runs of watch — did anything change?"
```
| Tool | Purpose | Key inputs |
|------|---------|-----------|
| `watch_create` | Create a watch (active → captures its baseline now) | `url`, `name?`, `intervalMinutes?`, `diffMode?` (visual/text/both), `threshold?`, `renderParams?`, `webhookUrl?` (Starter+), `notifyEmail?`, `paused?` |
| `watch_test` | Dry-run a config first (creates nothing) | same as `watch_create` |
| `watch_list` | List your watches | `status?` (active/paused/all), `cursor?`, `limit?` |
| `watch_get` | Fetch one watch (+ baseline URL) | `id` |
| `watch_run` | Run a check now (1 credit) | `id` |
| `watch_runs` | Run history with signed before/after/overlay URLs | `id`, `cursor?`, `limit?` |
| `watch_update` | Edit a watch in place — interval, diff mode, channels, render params | `id`, plus any `watch_create` field; `webhookUrl`/`notifyEmail` accept `null` to clear a channel |
| `watch_delete` | Delete a watch + its runs | `id` |
`renderParams` carries the per-check capture knobs (`fullPage` defaults to **true**, `selector`, `device`, `geo` (Pro+), plus noise controls `ignoreRegions`/`ignoreText`/`minTextChars`/`suppressWhilePresent` and `uaMode`). Interval floors are per-plan (Free 1440 / Starter 180 / Pro 30 / Enterprise 5). Watch metadata + signed image URLs are returned as JSON text.
### `rendex_account`
Check the account from inside the agent: which plan it's on, how many render credits have been used this month vs. the limit (and when it resets), the per-minute rate limit, and a one-tap upgrade link. Lets an agent answer "how much have I used?" or "how do I get more renders?" without sending the user to the dashboard. **Read-only — costs no credits.**
```
"How many Rendex renders do I have left this month?"
"What plan am I on, and how do I upgrade for more?"
```
Returns `{ plan, usage: { used, limit, remaining, unlimited, resetsAt }, rateLimitPerMinute, upgrade: { recommendedPlan, recommendedPlanCredits, upgradeUrl, manageBillingUrl } }`.
## Data templating
Turn one reusable template into many documents. Pass a `data` object alongside `html`
or `markdown`, and Rendex renders the string as a logic-less [Mustache](https://mustache.github.io/)
template before capture — `{{var}}` interpolation, `{{#items}}…{{/items}}` loops, and
nested `{{a.b}}` access. Great for invoices, reports, certificates, and OG cards.
```
"Render this HTML invoice template to a PDF, filling it with this data:
Invoice {{number}}
Total: {{total}}
data = { number: 'INV-014', total: '$2,400' }"
```
`data` is valid only with `html` or `markdown` — combining it with `url` returns a
validation error.
## Authentication
Get your API key at [rendex.dev](https://rendex.dev).
Set the `RENDEX_API_KEY` environment variable in your MCP client configuration.
## Pricing
| Plan | Calls/Month | Rate |
|------|------------|------|
| Free | 100 | 3/min |
| Starter | 10,000 | 60/min |
| Pro | 100,000 | 300/min |
| Enterprise | Custom | 1,000/min |
## License
MIT — [Copperline Labs LLC](https://copperlinelabs.com)