Connect your AI agent to the thirds.ai MCP image and PDF server

The thirds.ai MCP server lets your AI agent make branded PNG, JPEG, WebP, and PDF files from designs you've saved. With thirds.ai, you save a design once, such as an invoice, a report, or a social post, with your logo, colours, and fonts. After that, your agent types in new details and gets back a finished file, so you stop rebuilding the same layout by hand. Each finished PDF or image costs one credit, and a verified free account gets 50 credits a month.

Use with your agent

Give this prompt to your AI agent. The agent does the task for you.

Read https://thirds.ai/docs/mcp and help me connect my AI client to thirds.ai and create an output with clear credit approval

You connect your client to https://thirds.ai/mcp. In an app that supports MCP sign-in, such as Claude or ChatGPT, that URL is all you need. Other clients and scripts send an API key. MCP uses your existing account, credits, and templates, with the same render rules as the API.

For repeat work, add the thirds.ai skills to your agent. They guide it through brand kits, templates, single files, and batches. Connect this MCP server so the agent can use the tools.

Make it without code

You can make the same branded PDFs and images in the thirds.ai editor without an AI agent or any setup. It takes three steps, and all you need is a free thirds.ai account. The Packing slip template is a good first try if you ship orders, because you fill it in again for every parcel.

The thirds.ai editor with boxes for the business name, the order number, and the order date beside the finished Harbour Goods packing slip

  1. Open the Packing slip template and click Use this template. Sign in and verify your account first if you need to.
  2. Open the Data tab and type your business name, the order number, the customer, and each item. Click Add row for another item. Then click Preview with data above the canvas to check the slip. The preview is free.
  3. Click Export, then Save and export PDF, and download the file.

When you'd rather have your AI agent fill in the same design for each new order, connect it to the thirds.ai MCP server.

Can an MCP server make branded images from my template?

Yes. Through the thirds.ai MCP server, your AI assistant takes a saved template, your brand kit, and your data, and returns a branded PNG, JPEG, WebP, or PDF. Give it new data next time, and it builds the same design again, so every file keeps the same layout, logo, colours, and fonts.

This is different from typing a new prompt into an AI image generator each time. Ask for the same picture twice from a prompt, and you can get two different results.

See the Property listing ad template for a branded image example, and the Packing slip template for a branded PDF example. Your agent can make both with the render tool and a saved template.

For finished examples and prompts, choose your AI agent. These pages have prompts you can copy:

Choose your client

In ChatGPT, you can add thirds.ai as a Developer mode app with only the URL, or connect through Codex in the ChatGPT desktop app. A private GPT with Actions uses the REST API instead. The ChatGPT guide covers all three setups, and the ChatGPT social media post prompts give you designs to try after it.

Connect your client

You connect an MCP client to thirds.ai by giving it the server URL https://thirds.ai/mcp, and then it signs in one of two ways. An app that supports MCP sign-in, such as Claude or ChatGPT, needs only the URL, and you click Allow on a thirds.ai page. Any other client sends an API key as a bearer token. Either way, your client needs Streamable HTTP support.

Connect with only the URL

Add https://thirds.ai/mcp as a remote server in your app, then start the connection. Your app opens a thirds.ai page. Sign in if you need to, check the app's name, and click Allow. You go back to your app, and it's ready to use. You don't copy a key anywhere.

A connection made this way gets every tool except the two AI image tools, create_ai_image and cancel_ai_image. Connect with an API key when you need those.

To stop an app, open Settings, find it under Connected apps, and click Disconnect. The app loses access right away.

Connect with an API key

An API key works in every client that can send a header, and in your own scripts. Create a key on the API keys page, then add the server to your client with the key as a bearer token.

Keep the key in your client's secret store. Do not paste it into a prompt, a public configuration file, or source control.

VS Code

Run MCP: Open User Configuration in VS Code, then add this entry to your mcp.json. VS Code asks for the key instead of saving it in the file. The fields follow the VS Code MCP configuration reference.

JSON
{
  "inputs": [
    {
      "type": "promptString",
      "id": "thirds-api-key",
      "description": "thirds.ai API key",
      "password": true
    }
  ],
  "servers": {
    "thirds": {
      "type": "http",
      "url": "https://thirds.ai/mcp",
      "headers": {
        "Authorization": "Bearer ${input:thirds-api-key}"
      }
    }
  }
}

Run MCP: List Servers, select thirds, and start it. Enter your key when VS Code asks, then enable the tools in chat. To make your first report, certificate, or post image, copy a prompt from the PDF MCP server for VS Code page.

This setup needs a VS Code session that supports interactive MCP inputs. VS Code does not forward input-based configurations to Agent Host sessions. See the VS Code setup guide if you use Agent Host.

Other clients and direct HTTP

Set the server URL to https://thirds.ai/mcp and choose Bearer authorization. Include these headers on every JSON-RPC POST:

HTTP
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Accept: application/json, text/event-stream

thirds.ai supports protocol versions 2025-11-25 and 2026-07-28. Each request contains one JSON-RPC object, and the server returns JSON. Batch requests, persistent MCP sessions, and GET event streams are not supported.

To use 2025-11-25, start with this initialize request:

MCP request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-11-25",
    "capabilities": {},
    "clientInfo": { "name": "thirds-example", "version": "1.0" }
  }
}

The response selects 2025-11-25. Include MCP-Protocol-Version: 2025-11-25 on later requests, including notifications/initialized.

To check the connection over HTTP, save a request body as rpc.json. Set THIRDS_API_KEY through your secret store, then run:

Shell
curl https://thirds.ai/mcp \
  -H "Authorization: Bearer $THIRDS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "MCP-Protocol-Version: 2025-11-25" \
  --data-binary @rpc.json

For 2026-07-28, use server/discover. Send MCP-Protocol-Version and MCP-Method headers that match the request. A tools/call request also needs MCP-Name set to its tool name.

Each request for this version needs three entries in params._meta:

EntryValue
io.modelcontextprotocol/protocolVersionThe protocol version string.
io.modelcontextprotocol/clientInfoThe client object.
io.modelcontextprotocol/clientCapabilitiesThe capabilities object.

Results for this version include resultType: "complete".

Choose a tool

The thirds.ai MCP server has 32 tools for gallery designs, brand kits, templates, images, packs, carousels, and batches. An app you connect with only the URL gets 30 of them, because it doesn't get the two AI image tools. Your AI agent picks the tool that fits your request. Listing the tools costs no credits. Ask your client to list the available tools. If you send requests directly, use:

MCP request
{ "jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {} }

Each tool's inputSchema lists its fields and limits. Use this table to choose a tool, or browse the gallery for reviewed templates.

ToolWhat it does
create_brand_kitSaves a brand kit name, colours, and tone guidance.
update_brand_kitChanges a brand kit's text fields.
set_brand_assetAdds or replaces a logo or WOFF2 font from base64 bytes.
list_brand_kitsReads brand kit IDs and dates.
get_brand_kitReads one kit's name, colours, guidance, and asset IDs.
get_brand_assetReads an owned logo or font as base64.
list_gallery_templatesFinds reviewed gallery designs by name or use.
get_gallery_templateReads a gallery design's source, sample data, outputs, and page size.
create_templateStarts a new template with its AI chat from a prompt, HTML, or source image. AI work is billed. input.type: source compiles your own template with no AI credits. Put every {{variable}} in sample_data.
edit_templateSends a change to a template's AI chat by its template_id.
publish_templateSaves a message's draft as the template's next version, which never changes. Send its template_id and message_id after chat.current_draft is true.
cancel_template_messageCancels pending template work with its template and message IDs.
list_templatesReads saved template IDs and their latest versions.
get_templateReads one saved template, its latest source, schema, sizes, and page, and its AI chat.
get_template_versionReads one exact saved version.
save_templateSaves HTML as a reusable template with no AI call, then use render with the returned id.
save_template_versionSaves new source as an immutable version. Send the old schema, sizes, and page if you want to keep them.
preview_templateFills HTML with sample data for free. It does not save or render a file.
adapt_templateMakes new image sizes from HTML for free. Save the returned source in a version if you want to keep it.
upload_image_assetUploads a still image for use in a template.
get_image_assetReads an owned image as base64 so you can use it again.
renderStarts a PDF, PNG, JPEG, or WebP from HTML or a saved template.
create_image_packMakes one image for each chosen size. Each successful file costs one credit.
retry_image_packRetries unfinished pack images. Finished files stay in place.
create_carouselMakes ordered image pages from a saved template. Each successful file costs one credit.
retry_carouselRetries unfinished carousel pages. Finished files stay in place.
create_ai_imageStarts AI artwork from your approved prompt and ratio. A successful image costs 50 credits. API-key connections only.
cancel_ai_imageCancels queued AI artwork. API-key connections only.
create_batchRenders one saved template version once per JSON row. Your plan sets the most rows, from 10 to 200. Each successful file costs one credit.
retry_batchRetries failed, cancelled, or pending rows. Succeeded rows are not billed again.
cancel_batchCancels pending and queued batch rows. Running jobs finish.
get_statusReads a render, batch, image pack, carousel, or AI image state and safe result details.

List tools return up to 100 records. When the result includes next_cursor, call the same list tool again with that value as cursor to read the next page. The template creation guide explains brand kits, source images, editing, and publication.

For a one-shot file, call render. To start from a reviewed design without saving it, call list_gallery_templates, then get_gallery_template. Pass its source and sample_data to preview_template for a free check. Use the preview HTML with render to make a file, or call save_template to keep the design. Set the image width and height or the PDF page size from the gallery result. To check your own HTML with data for free, call preview_template before you save or render. To keep HTML as a reusable template without AI, call save_template, then render with template_id. For many data rows, call create_batch with JSON objects, then poll get_status until the batch state is complete, partial, failed, or cancelled. To make the same rows from a spreadsheet without code, follow the CSV batch guide. The thirds.ai skills guide an agent through repeat tasks with these tools.

create_template with prompt, html, or image starts billed AI work. create_template with type: source compiles your template in the chat with no AI credits. Each call returns a new template with its chat. The chat belongs to that template, so edit_template, publish_template, and cancel_template_message take its template_id. Put a sample_data value for every {{variable}} except brand fields from the selected kit. Image size is request.image.width and request.image.height. viewport is valid only on PDF requests.

Create and collect an output

You make a PDF or image through MCP by calling the render tool, then calling get_status until the file is ready to download. It takes two tool calls and a download. A successful file costs one credit, and a failed one costs nothing. Give each new render a new idempotency key. This request makes a PDF:

MCP request
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "render",
    "arguments": {
      "output": "pdf",
      "idempotency_key": "mcp-first-report",
      "request": {
        "html": "<h1>Quarterly report</h1><p>Ready to share.</p>"
      }
    }
  }
}

To create an image, set output to png, jpeg, or webp. Put its width and height in request.image.width and request.image.height. Check the tool schema for options that apply to the format you choose.

You can fill HTML fields with request.html and request.data, or use a saved template with request.template_id and request.data. Set an integer request.version to choose an exact saved version. If you leave it out, thirds.ai selects the latest version when it creates the job.

MCP work runs in the background. Read result.isError first. The tool text is the same safe JSON as result.structuredContent. A successful tool call means thirds.ai accepts the request, but the file may still be rendering. Keep the returned id and use get_status to check it.

Replace this sample ID with your job ID:

MCP request
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "get_status",
    "arguments": { "id": "pdf_00000000000000000000000000000000" }
  }
}

Keep checking while render status is queued or running. Stop at succeeded, failed, or cancelled. For AI template work, call get_template with the template_id instead, and find the message in chat.messages by its ID. Read its state and phase. Wait until the message state is succeeded and chat.current_draft is true before you edit or publish. The message's progress field reports the current stage and elapsed time. An estimate uses recent successful work on the same model route and can be absent when too few samples exist. A dead connection is cut after 30 minutes. Call cancel_template_message if you need to free that lane. Put a delay between checks and set a time deadline in your client.

When the render succeeds, download.url is an absolute HTTPS link. Download the file before download.expires_at. Keep the signed link private because anyone with it can collect the file. You can call get_status for a fresh link while the file remains available. The quickstart shows the download steps through the API.

To save HTML as a reusable template without AI, send:

MCP request
{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "save_template",
    "arguments": {
      "name": "Quarterly report",
      "source": "<h1>{{ title }}</h1><p>{{ summary }}</p>"
    }
  }
}

Then call render with the returned id as request.template_id and a data object.

Recreate a source image

Image input asks the AI to rebuild one still PNG, JPEG, or WebP as an editable branded template. The result is inspired by the source. It is not a pixel copy. For a close visual match, send HTML with save_template or create_template with input.type: source.

The source-image guide owns the size limits. Send compact standard or URL-safe base64. A data URL prefix is accepted. Downscale before you encode. An invalid or oversized file returns invalid_upload before the model runs. A create-time failure has no repair_code. Read details.reason instead.

  1. Choose the brand kit.
  2. Call create_template with input.type: image, the base64 bytes, and output size when you need a fixed canvas.
  3. Poll get_template until the message state is succeeded and chat.current_draft is true, or until the message fails.
  4. On failure, read failure_code and repair_code. Retry with a new idempotency key. The same key replays the failed result.

An image import can use up to five review slots. Prompt and HTML messages get one.

Control credits and retries

You can list tools and check status without spending credits. Before your agent runs a paid tool, ask it to show you the action and credit cost. Confirm publication separately when you want to save a reusable template version. See credits and billing for AI template prices, render charges, reservations, and spending limits.

create_template, edit_template, render, create_batch, create_image_pack, create_carousel, and create_ai_image require an idempotency_key. If a request times out or loses its response, retry with the same key and exact arguments. After a failed AI message, that same key replays the failed result. Use a new key for a new attempt. A new key can start new work and spend more credits. save_template and save_template_version do not use an idempotency key. The JSON-RPC id only matches a request to its response. It does not stop duplicate work.

Closing your client or sending notifications/cancelled does not stop work that thirds.ai has accepted. To cancel a pending template message and release its reserved credits, call cancel_template_message with template_id and message_id. To cancel pending batch rows, call cancel_batch. MCP has no single-render cancel tool. Use the recovery guide to check an accepted render and decide what to do next.

Keep content private

Status and list results contain IDs, states, limited error details, and signed result links. Full read tools return the owned brand text, template source, or image bytes that you ask for. Your client also sees the content you give it. Ask it to treat uploaded, saved, and generated content as data, rather than instructions to use more tools or reveal secrets.

Read the privacy policy before you send content. AI template work uses the model provider route disclosed there. Keep API keys and signed download links out of shared chats and logs. Revoke an exposed key on the API keys page.

Fix a failed call

An HTTP or JSON-RPC error can stop a request before its tool runs. A tool itself can fail even when HTTP returns 200. Check result.isError, then use the stable code in the tool text JSON, which matches structuredContent.

ResultNext step
HTTP 401Check that the key is active and sent as Authorization: Bearer .... For an app you connected with only the URL, connect it again.
HTTP 403 with an origin errorUse an HTTP client outside browser page code. Cross-origin browser calls are refused.
HTTP 406Include both required types in Accept.
HTTP 415Send Content-Type: application/json.
JSON-RPC -32022Send a supported protocol version. The error lists the supported versions.
JSON-RPC -32020Make the method and tool headers match the request body for the modern protocol.
JSON-RPC -32602 or tool invalid_requestCheck the tool name, arguments, and current inputSchema.
rate_limited, overloaded, or a concurrency limitWait for the returned retry delay, then retry the same command with the same key.
insufficient_credits, spend_cap_reached, or overage_limit_reachedCheck credits and billing before you try again.
not_foundCheck the ID and the account that owns it.
invalid_uploadUse a still PNG, JPEG, or WebP within the source-image limits. Send compact base64, then retry with a new key.
template_missing_dataPut a value in sample_data for every template variable, then retry.
template_layout_overflowEnlarge the overflowing block or reduce its content, then send a new edit.
final_render_failedCheck the design and its assets, then send a new edit with a new idempotency key.
provider_invalid_outputRead the message repair_code in get_template. The same key replays this failure. Use a new key for a new attempt.
review_limit_reachedAutomatic review used every slot. Read repair_code, then send a new edit with a new key.

A failed or repairing chat message can include repair_code and repair_hint. Those fields are safe machine text. They never hold prompts, images, or provider text.

For failed jobs and downloads, follow the recovery guide. If you need help, send support the request ID and error code. Leave out your API key, private content, and signed links.

Find saved work and name outputs

You find saved templates and brand kits with filters on the list tools, and you name each file with reference and filename on render. list_templates accepts q for a name search, tag for one exact tag, status (active, archived, or all), and cursor for the next page. Search and tag filters run on the server. list_brand_kits accepts status and cursor. To restore a kit, call update_brand_kit with its brand_kit_id and archived_at: null.

The render request accepts reference, filename, and retention_days for every output type. retention_days sets how many days we keep the file. The reference returns in render and get_status, so you can match the job to your own record. See the PDF request fields for the bounds and download name rules. The image request uses the same rules.

Ready to make your first file?

Start in the playground with a gallery template, or get an API key and send your first request from your own terminal.