API and MCP recipes
Three hand-written recipes for render.cuelark.com: an n8n HTTP Request that saves a 1200×630 Open Graph PNG, Cursor connected to the MCP server, and a Next.js generateMetadata helper that uses the image URL directly. We ran each HTTP and MCP call on 15 Nov 2026. No API key is required for charts or cards.
1. n8n: download an OG image
n8n's HTTP Request node can treat the response as a file. Point it at a GET /v1/og URL. The same URL is valid in curl, which is what we tested: HTTP 200, image/png, 1200×630.
- Add a Manual Trigger and an HTTP Request node (type version 4.2 works).
- Method: GET. URL: the query below. Options → Response → Response Format: File.
- Run the workflow. The binary output is
card.png. You can post it to Slack, attach it to email, or write it to disk.
curl -sL "https://render.cuelark.com/v1/og?template=blog&title=How+we+ship+faster+with+fewer+meetings&description=Five+habits+from+a+remote+team&eyebrow=Blog&author=Sam+Lee&site=example.com" -o card.pngTo make a chart instead, POST JSON to /v1/chart. At scale: 2 the PNG is 1600×900. We tested this body too:
curl -sL -H 'content-type: application/json' \
-d '{"chart":{"type":"bar","title":"Signups by channel","labels":["Organic","Paid","Referral"],"datasets":[{"label":"November","data":[56,29,18]}]},"scale":2}' \
-o chart.png https://render.cuelark.com/v1/chartImportable n8n workflow (trigger + HTTP Request, response format File):
{
"name": "Cuelark OG image",
"nodes": [
{
"parameters": {},
"id": "start-cuelark-og",
"name": "When clicking ‘Test workflow’",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
0,
0
]
},
{
"parameters": {
"url": "https://render.cuelark.com/v1/og?template=blog&title=How+we+ship+faster+with+fewer+meetings&description=Five+habits+from+a+remote+team&eyebrow=Blog&author=Sam+Lee&site=example.com",
"options": {
"response": {
"response": {
"responseFormat": "file"
}
}
}
},
"id": "http-cuelark-og",
"name": "Download OG image",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
260,
0
]
}
],
"connections": {
"When clicking ‘Test workflow’": {
"main": [
[
{
"node": "Download OG image",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"meta": {
"templateCredsSetupCompleted": true
}
}2. Cursor: Render MCP server
The server lives at https://render.cuelark.com/mcp (Streamable HTTP, no sign-in required for charts and cards). Same install format as the MCP setup page.
- Save this as
.cursor/mcp.jsonin your project, or paste it under Cursor Settings → MCP. - Reload MCP. You should see four tools: render_chart, social_card, html_to_pdf and screenshot_url.
- Ask Cursor: “Call social_card with template blog, title ‘How we ship faster with fewer meetings’, description ‘Five habits from a remote team’, author Sam Lee, site example.com.” It returns a PNG, a permanent image URL, and meta tags you can paste.
{
"mcpServers": {
"cuelark-render": {
"url": "https://render.cuelark.com/mcp"
}
}
}Equivalent tool arguments (we called tools/call with this payload; the returned URL is a 1200×630 PNG):
{
"name": "social_card",
"arguments": {
"template": "blog",
"title": "How we ship faster with fewer meetings",
"description": "Five habits from a remote team",
"eyebrow": "Blog",
"author": "Sam Lee",
"site": "example.com"
}
}3. Next.js: generateMetadata and og:image
The GET URL is the image, so you do not need a Route Handler or opengraph-image.tsx unless you want the file to be served from your own origin. Put the URL in generateMetadata. The helper below produces the same URL we fetched: https://render.cuelark.com/v1/og… (1200×630 PNG, cached).
- Copy the generateMetadata helper into your App Router project (Next.js 13+).
- Pass each page's title, description and author into ogImageUrl.
- Set openGraph.images and twitter.images to that URL, with width 1200 and height 630.
import type { Metadata } from "next";
const API = "https://render.cuelark.com";
export function ogImageUrl(post: {
title: string;
description?: string;
author?: string;
date?: string;
}): string {
const q = new URLSearchParams({
template: "blog",
title: post.title,
site: "example.com",
eyebrow: "Blog",
});
if (post.description) q.set("description", post.description);
if (post.author) q.set("author", post.author);
if (post.date) q.set("date", post.date);
return `${API}/v1/og?${q}`;
}
export function generateMetadata({ post }: { post: { title: string; description: string; author?: string } }): Metadata {
const image = ogImageUrl(post);
return {
title: post.title,
description: post.description,
openGraph: {
title: post.title,
description: post.description,
images: [{ url: image, width: 1200, height: 630, alt: post.title }],
},
twitter: { card: "summary_large_image", title: post.title, description: post.description, images: [image] },
};
}
// Example values used in the test (swap in your CMS post):
export const examplePost = {
"title": "How we ship faster with fewer meetings",
"description": "Five habits from a remote team",
"author": "Sam Lee"
};
Preview the example image: https://render.cuelark.com/v1/og?template=blog&title=How+we+ship+faster+with+fewer+meetings&description=Five+habits+from+a+remote+team&eyebrow=Blog&author=Sam+Lee&site=example.com
Full parameter lists are on the API docs. Limits, errors and URL safety rules are unchanged. Recipes last tested 15 Nov 2026.
Frequently asked questions
Do I need an API key?
No. Charts and social cards are free today, with a rate limit of 120 requests per minute per IP. Browser renders (PDF and screenshots) have a small daily cap. You can add a Render-scoped key later at auth.cuelark.com if you want a higher cap.
How do I get a chart PNG in n8n, not just an OG image?
Use an HTTP Request node with POST to https://render.cuelark.com/v1/chart, Content-Type application/json, and a body like the chart example on this page. Set the response format to File so the next node receives a PNG (1600×900 at scale 2).
Where does the Cursor MCP config go?
Put the JSON in your project's .cursor/mcp.json, or in Cursor Settings → MCP. After it connects you should see four tools: render_chart, social_card, html_to_pdf and screenshot_url. Then ask Cursor to call social_card with a title and template.
Should Next.js use the /v1/og URL as og:image, or fetch and host the PNG?
Use the URL as og:image. GET /v1/og is the image: it is cached at the edge (24 hours in browsers, 30 days at the CDN) and needs no key. Fetch-and-host is only needed if you upload a logo or background photo, because those POST-only cards have no permanent URL.
Can I put a logo on the card from Next.js or n8n?
Yes, with POST /v1/og and a logo or bgImage field as a base64 data URL under the size cap. Those cards are not given a permanent query URL, so save the PNG and host it with your site.