MCP
MCP tools
Read templates and generate images and PDFs from an MCP client.
The Bannerify MCP server exposes six tools. The assistant picks them automatically from your request, so you rarely call them by name.
Every tool works only on the workspace that approved the connection.
Tools
| Tool | What it does | Arguments |
|---|---|---|
list_templates |
Lists the templates in the workspace, with the layers you can override | includeLayers (boolean, optional) |
get_template |
Reads one template and its layers | templateId (string) |
get_project |
Reads the linked project, its plan, and its creation date | none |
create_image |
Renders a template and returns the image | templateId (string), modifications (object, optional), format (png, jpeg, webp) |
create_pdf |
Renders a template as a PDF and returns a download link | templateId (string), modifications (object, optional) |
create_image_from_shapes |
Composes an image from shapes, with no template | shapes (array), canvas (object, optional), format (png, jpeg, webp) |
A template id looks like tpl_xxxxx.
Find a template
Ask for the templates and their layers:
List my Bannerify templates, with the layers of each one.
The answer names every template and, for each layer, the name to use in modifications, for example:
[
{
"id": "tpl_lifecycle",
"name": "Lifecycle email",
"layers": [
{ "name": "headline", "type": "text", "suggestInput": "text" },
{ "name": "photo", "type": "image", "suggestInput": "src" },
{ "name": "qr", "type": "qrcode", "suggestInput": null }
]
}
]
Layer names come from the template editor, so keep them descriptive: headline, price, qr, photo.
Pass layer values
modifications is an object keyed by layer name. A string sets the text of a layer. An object sets that layer’s own fields.
| Layer type | Example value |
|---|---|
| Text | { "headline": "Summer sale" } |
| Image | { "photo": { "src": "https://example.com/photo.png" } } |
| QR code | { "qr": { "qrcode": "https://example.com/restart" } } |
| Table | { "table": { "rows": [["Plan", "Price"], ["Pro", "$29"]] } } |
| Any layer | { "tag": { "visible": false } } |
A full example for create_image:
{
"templateId": "tpl_lifecycle",
"format": "png",
"modifications": {
"headline": "Welcome back, An",
"price": "$29",
"photo": { "src": "https://example.com/hero.png" },
"qr": { "qrcode": "https://example.com/restart" }
}
}
Layers you leave out keep the values from the template.
Read the result
create_image returns the image itself, so the assistant can show it or save it to a file. create_pdf stores the file and returns a link:
Generated a PDF from template tpl_lifecycle. Download: https://images.bannerify.co/files/mcp/9f1c....pdf
The link points to the Bannerify CDN and stays available like any other stored asset.
Compose an image without a template
Use create_image_from_shapes when no template fits. Give the tool a canvas and a list of shapes. It draws the shapes in order and returns the image, so the assistant can design a one-off banner, label, or invoice.
Every shape has type, x, y, width, and height, in pixels from the top left of the canvas. The first shape is at the back and the last is on top.
| Type | Required | Optional |
|---|---|---|
text |
text |
fontSize (24), align (left, center, right), lineClamp, color, fontFamily, fontWeight |
frame |
— | backgroundColor, borderColor, borderWidth, borderRadius |
image |
src |
objectFit (cover), borderRadius |
qrcode |
qrcode |
backgroundColor |
barcode |
barcode |
— |
icon |
icon |
color |
star |
— | star (1 to 5), color |
table |
columns, rows |
footer, variant, stripe, compact, align, fontFamily |
A few rules:
icontakes an Iconoir name, for examplecheck-circleorarrow-right.srcandcanvas.backgroundImagetake an HTTPS URL or a data URL.canvas.backgroundImagealso takes a CSS gradient, for examplelinear-gradient(to right, #4f46e5, #9333ea).styletakes CSS property names for the rest:padding,boxShadow,borderStyle,lineHeight, and similar. Set the size withwidthandheight, not withstyle.- Table
columnsare the headers androwshold one value per column in the same order. - Limits: 1 to 100 shapes, 16 to 4096 pixels on each side of the canvas, 4000 characters of text, 200 table rows, 12 table columns.
The canvas is white unless canvas.background is set. canvas.backgroundImage wins over canvas.background.
A full example: an invoice.
{
"canvas": { "width": 800, "height": 560, "background": "#f8fafc" },
"shapes": [
{ "type": "frame", "x": 0, "y": 0, "width": 800, "height": 120, "backgroundColor": "#0f172a" },
{ "type": "text", "x": 48, "y": 44, "width": 400, "height": 40, "text": "INVOICE", "fontSize": 30, "color": "#ffffff" },
{ "type": "text", "x": 500, "y": 52, "width": 252, "height": 24, "text": "INV-1042", "fontSize": 18, "align": "right", "color": "#94a3b8" },
{
"type": "table",
"x": 48,
"y": 176,
"width": 704,
"height": 180,
"columns": ["Item", "Qty", "Total"],
"rows": [["Logo pack", 1, "$29.00"], ["Banner credits", 500, "$19.00"]],
"footer": ["", "Due", "$48.00"],
"variant": "striped",
"compact": true
},
{ "type": "text", "x": 48, "y": 392, "width": 300, "height": 28, "text": "Thank you for your business.", "fontSize": 16, "color": "#475569" },
{ "type": "qrcode", "x": 632, "y": 384, "width": 120, "height": 120, "qrcode": "https://bannerify.co/invoices/1042" }
]
}
A generation from shapes counts against the same monthly and daily quota as a generation from a template. See Quota and limits.
Handle errors
A failed tool call returns a message with the error code, using the same codes as the REST API:
| Code | Meaning | What to do |
|---|---|---|
NOT_FOUND |
The template does not exist in this workspace | Run list_templates and use a returned id |
UNAUTHORIZED |
The connection is no longer valid | Remove the server from your MCP client and add it again |
USAGE_EXCEEDED |
The workspace reached its monthly or daily generation limit | Wait for the next period, or check Quota and limits |
TOO_MANY_REQUESTS |
Too many requests arrived in a short time | Retry after a short wait |
BAD_REQUEST |
A layer value does not match its layer, or a shape spec is not valid | Check the layer with get_template, or the shape fields above |
FETCH_IMAGE_ERROR |
A remote image could not be downloaded | Use a public URL that returns an image |
See Errors for the full list.