Announcing CIMD support for MCP Client registration
Learn more

Building an Agent on Canva: MCP Server or Connect API?

Nishant Choudhary
Tech Evangelist

TL;DR

  • The capability gap runs in both directions. Canva's remote MCP exposes AI design generation and transaction-based in-place editing that the Connect API has no endpoint for. The Connect API exposes webhooks, design analytics, page merges, and raw-byte asset uploads that the MCP does not.
  • Both paths are OAuth per-user. Neither offers an API key or a service account. The MCP uses Client ID Metadata Documents (CIMD), with Dynamic Client Registration (DCR) deprecated. The Connect API uses the Authorization Code flow with PKCE, a registered integration, and access tokens that currently expire after four hours.
  • Pointing your own production agent at Canva's remote MCP requires applying to a waitlist to allowlist your redirect URI. The Connect API requires registering an integration and submitting it for review before anyone outside your team can connect.
  • MCP is the faster path for interactive, user-present design assistants. The Connect API is the right foundation for headless, event-driven, deterministic pipelines and for anything the MCP does not expose.
  • Neither path gives you a token vault, rotation, or per-tenant revocation. Scalekit's Canva connector ships 48 Connect API tools over OAuth 2.0 and handles that credential layer for you, so the MCP vs API decision does not change your auth infrastructure.

Your agent needs to make, move, or export something in Canva. Canva now ships two distinct paths: a remote MCP server aimed at AI assistants, and the Connect API your integration may already call. They cover overlapping but genuinely different territory, they put you on different OAuth paths, and they impose different operational demands in production. This is the decision framework for agent builders.

What Canva MCP and the Canva Connect API actually are

Both surfaces reach the same Canva account, but they are built for different consumers and are gated differently. Here is what each one is before we compare them.

Canva MCP: the remote AI Connector

Canva provides a remote MCP server at mcp.canva.com/mcp, marketed as the Canva AI Connector. It exposes design generation, in-place editing, discovery, asset and brand management, export, and commenting as MCP tools so an assistant can act on a user's Canva through natural language. Authentication is per-user OAuth: Canva stores designs, assets, and permissions per user, not at the org level, so every user of your assistant authenticates individually. Read the details in Canva's official MCP documentation.

The Canva Connect API: OAuth and REST

The Connect API is a REST interface at api.canva.com/rest/v1, covering designs, assets, autofill, brand templates, comments, folders, exports, design imports, merges, resizes, users, webhooks, and analytics. It authenticates with the OAuth 2.0 Authorization Code flow plus PKCE, using a registered integration (client_id and a client_secret that begins with cnvca). Access tokens currently expire after four hours; you refresh with a refresh token. Full reference lives in Canva's official Connect API documentation.

One Scalekit connector, built on Connect

Scalekit exposes a single Canva connector, built on the Connect API, shipping 48 prebuilt tools over OAuth 2.0. There is no separate Scalekit "Canva MCP" connector to choose between; the connected-account model is the same whichever Canva surface you reason about. The setup and tool list are in the Scalekit Canva connector docs.

Comparing them where it matters for agents

The choice is not "richer vs simpler." For Canva specifically, each path holds capabilities the other cannot reach, and the auth models diverge in ways that decide production viability. Four dimensions carry the comparison.

What your agent can actually do

The table below maps the actions most relevant to agent use cases. Read it as a coverage map, not a scorecard; the right column depends on what your agent is for.

Capability
Canva MCP
Canva Connect API
Create a design (preset, custom, from asset)
Yes
Yes
Generate a design from a text prompt (AI)
Yes
No
Edit design content in place (transactions)
Yes
No
Autofill a brand template with data
Enterprise only
Yes (Enterprise or trial)
Search designs, folders, brand templates
Yes
Yes
Export as PDF, PNG, JPG, PPTX, MP4
Yes
Yes
Comment threads and replies
Yes
Yes (preview)
Upload an asset
From URL only
From URL and raw bytes
Resize a design to new dimensions
Pro and above
Yes
Merge design pages
No
Yes
Design view analytics (views, viewers)
No
Yes (Enterprise, preview)
Webhooks and real-time events
No
Yes (preview)

Where the capability gap runs in both directions

The unusual part of Canva is that neither surface is a strict superset. The MCP owns AI-native creation: generating a design from a prompt and editing an existing design in place through a start, perform, commit transaction cycle. The Connect API has no editing endpoint and no text-to-design generation, so those live only on the MCP path. Going the other way, the Connect API owns the operational surface: webhook notifications for real-time events, design view analytics, page merges, and direct byte uploads. If your agent reacts to changes or runs unattended, that surface is not optional.

The auth path each one puts you on

There is no API-key shortcut on either path; both are per-user OAuth. The MCP recommends CIMD, where your client_id is an HTTPS URL pointing to a JSON document describing your client, so you avoid pre-registration and a client secret; DCR remains for backward compatibility but is deprecated. The Connect API uses Authorization Code with PKCE against a registered integration, with short-lived access tokens. If you are weighing these token models generally, see OAuth vs API keys for AI agents and the CIMD vs DCR guide.

The gating step people miss

Each path has a real gate before a non-trivial agent can connect. To point your own production agent or platform at Canva's remote MCP, you must apply to a waitlist to allowlist your redirect URI; end users of popular assistants get access, but your custom integration does not by default. On the Connect API path, your integration starts in draft and works only for your own team until you submit it for review and Canva approves it for production. Both gates are architectural, not paperwork you can skip.

What you own in production

On the MCP path, Canva runs the server, maintains the tool schemas, and normalizes responses; you still own per-user token storage, refresh, revocation on disconnect, and tenant isolation. On the Connect API path, you own the full stack: endpoint selection, error handling, pagination, retries, and the token lifecycle. The four-hour access-token expiry is the sharp edge here: a long-running or scheduled agent will hit expiry mid-run unless refresh is handled proactively. That failure mode is covered in how to handle token refresh for AI agents.

When to use Canva MCP

Reach for the MCP when the work is interactive and a user is present to authorize it.

  • Your agent is a user-facing design assistant where OAuth consent in a browser is natural, for example inside Claude, ChatGPT, or a chat surface you ship.
  • The job is AI generation or conversational editing: draft a graphic from a prompt, then tweak copy, colors, or images in place.
  • You want Canva to maintain the tool schemas and you do not need webhooks, analytics, or unattended runs.
  • You are prototyping and want a working Canva agent without writing REST integration code.

When to use the Canva Connect API

Reach for the Connect API when the agent runs on its own or needs surface the MCP does not expose.

  • Your agent is headless: scheduled asset generation, autofill pipelines, export batches, or sync jobs with no user in the loop.
  • You need capabilities absent from the MCP: webhook notifications, design view analytics, page merges, or raw-byte uploads.
  • You are running a deterministic pipeline where versioned endpoints and predictable schemas matter more than automatic tool updates.
  • You are building a multi-tenant B2B product where each customer authorizes their own Canva and you need per-user scoping and revocation.

The credential problem that exists on both paths

The path decision changes the token type. It does not change the infrastructure you need underneath it. This is the part that determines whether your Canva agent survives its second customer.

Both paths hand you a per-user token, not a vault

MCP OAuth gives you a token per user. Connect API OAuth gives you an access token and refresh token per user. In neither case do you get encrypted-at-rest storage, per-tenant isolation, rotation logic, or a revocation flow. Those are yours to build regardless of which surface you chose.

The N-credential problem in a multi-tenant Canva agent

In a multi-tenant B2B agent, which is the norm rather than the exception, every user holds their own Canva credential. Fifty customers is fifty token lifecycles to store, refresh, and revoke. The Connect API's four-hour access tokens turn refresh from a background nicety into a correctness requirement, and employee offboarding creates a specific gap: the identity provider account is disabled, but a Canva token minted months ago and stored locally is still valid until someone invalidates it. For the wider pattern, see access control for multi-tenant AI agents.

Where Scalekit fits

Scalekit's Canva connector resolves the per-user connected account on every tool call, handling the OAuth flow, encrypted token storage, and refresh for the four-hour token, so credentials never touch the agent runtime. The same auth infrastructure works whether you reason about the MCP surface or call the Connect API directly; the path decision does not change what you need at the credential layer.

Building a Canva agent with Scalekit, in Python with LangChain

The fastest way to see the model is to build one. This walkthrough connects a user's Canva account, loads only the tools that user authorized, and runs an agent loop with LangChain. Prerequisites: a Scalekit account, the Canva connection configured in the dashboard, and your Scalekit credentials in .env.

Install and initialize

Install the SDK and create a client. The client reads your Scalekit environment URL, client ID, and client secret from the environment.

# pip install scalekit-sdk-python langchain-anthropic langgraph import os from scalekit import ScalekitClient scalekit = ScalekitClient( env_url=os.environ["SCALEKIT_ENVIRONMENT_URL"], client_id=os.environ["SCALEKIT_CLIENT_ID"], client_secret=os.environ["SCALEKIT_CLIENT_SECRET"], ) actions = scalekit.actions # The connection name must match the connection you created in the Scalekit # dashboard. For Canva the default is "canva"; it is not a provider slug. CONNECTION = "canva" IDENTIFIER = "user@example.com" # your app's stable per-user identifier

Authorize the user's Canva account

Before the agent can act, the user authorizes their Canva account once. Scalekit returns a link; send the user through it, and Scalekit stores the resulting connected account against your identifier.

link_response = actions.get_authorization_link( connection_name=CONNECTION, identifier=IDENTIFIER, ) print("Authorize Canva:", link_response.link) # After the user completes consent, Scalekit holds the connected account.

Load the user's scoped Canva tools

Now load the tools. The agent does not receive a flat catalog of all 48 Canva tools; it receives the tools this user's connected account is authorized to call, mapped straight into LangChain structured tools. Cutting the surface from 48 to the handful the task needs reduces token overhead and improves tool selection; more on that in LangChain tool calling.

tools = actions.langchain.get_tools( identifier=IDENTIFIER, connection_names=[CONNECTION], page_size=50, )

Run the agent loop

Bind the scoped tools to a tool-calling model and run. Every Canva call the agent makes executes under this user's connected account, not a shared credential.

from langgraph.prebuilt import create_react_agent from langchain_anthropic import ChatAnthropic llm = ChatAnthropic(model="claude-sonnet-4-5") # any tool-calling model agent = create_react_agent(llm, tools) result = agent.invoke({ "messages": [( "user", "Find my 'Q3 Launch' design and export it as a PDF, then give me the link.", )], }) print(result["messages"][-1].content)

The same connect and execute in TypeScript

If your stack is Node, the connected-account model is identical. Authorize once, then call a specific tool by name against the user's connection.

import { ScalekitClient } from '@scalekit-sdk/node' import 'dotenv/config' const scalekit = new ScalekitClient( process.env.SCALEKIT_ENVIRONMENT_URL!, process.env.SCALEKIT_CLIENT_ID!, process.env.SCALEKIT_CLIENT_SECRET!, ) const actions = scalekit.actions const { link } = await actions.getAuthorizationLink({ connectionName: 'canva', identifier: 'user@example.com', }) console.log('Authorize Canva:', link) // After the user authorizes, execute a tool under their connected account. const result = await actions.executeTool({ connector: 'canva', identifier: 'user@example.com', toolName: 'canva_design_list', toolInput: {}, }) console.log(result)

Why build Canva agents the Scalekit way

The connector removes the credential work, but the reason to route Canva through Scalekit goes past auth plumbing. Three things matter once the agent leaves your laptop.

Per-user auth logs and tool observability

Because every Canva call resolves through a per-user connected account, each tool invocation is attributable to the user who authorized it. That gives you downstream tool-calling logs for who did what, when, under whose credentials, which is exactly what a security reviewer asks for. See agent tool observability for the full picture.

Virtual MCP for multi-tool, multi-tenant agents

If your agent uses Canva alongside other tools, a Virtual MCP server gives it a scoped, per-user MCP endpoint declaring exactly which tools it can see and whose credentials it acts with, with no MCP server to deploy, host, or maintain. One server definition serves all users; each run gets a short-lived session token scoped to that user's connected accounts. This is also the clean way to expose Canva to an assistant without going through Canva's redirect-URI waitlist. Start with the Virtual MCP overview and the Virtual MCP deep dive.

One connector, both worlds

The same connected-account model underpins Scalekit's agent templates, from outbound and content workflows to multi-tool orchestration. Browse the wider set on the Scalekit connectors directory, and compare adjacent design tooling in the Figma MCP vs API breakdown. Pricing for scaling this across tenants is on the Scalekit pricing page.

Which one to build against

If your Canva agent is interactive and its core job is generating or conversationally editing designs with a user present, the remote MCP is the faster route, and it is the only path to AI generation and in-place editing. If your agent runs unattended, reacts to events, needs analytics or merges, or acts across many customer accounts, build against the Connect API, since webhooks, analytics, and headless execution live only there. Most production products end up using both: the MCP for user-facing creation and the Connect API for background pipelines. Whichever surface you pick, the per-user credential problem is identical, and that is the layer that needs production-grade infrastructure.

Talk to us, or start building

Building Canva agents and want a second opinion on the auth model? Join the Scalekit community on Slack or reach an engineer through the Talk to us page for immediate help.

Set up the connector from the Scalekit Canva connector docs, or see it on the Canva connector page.

No items found.
Agent
Auth Quickstart
On this page
Share this article
Agent
Auth Quickstart

Acquire enterprise customers with
zero upfront cost.

Every feature unlocked. No hidden fees.