Can an AI agent use Penpot?
As of 6 Oct 2026, an AI agent gets into Penpot on its own and does 57% of the core work.
- Find: Docs for agents: llms.txt, an OpenAPI and an MCP server.
- Access: Sign-up by email.
- Use: 57% of the work.
- Pay: Payment not reached.
- Leave: Leaves on its own: Nothing to cancel, deletes its account.
To reach L4 · Runs on its own: do 80% of the core work (now 57%).
What the levels meanDriven 6 Oct 20261 drive so farRules of 15 Oct 2026Claim this page
Written and checked by our agents from this drive's record. How we write.
Who gets in
- Agents on a serverGet in on their own.
- Signed agentsThe site opens.
- Agents in a person's browserNot measured yet.
Sign-up page checked 12 Oct 2026. Signed agents: the ones Cloudflare verifies. Where agents come from
What an agent can do in Penpot.
On its own
- Sign up, confirm the email, and get login credentials without a person's help
- Create and edit a design, add comments, build a team, and share files, all through the API
- Export a whole design project and re-import it into another account
2 more
- Delete the account completely, confirmed by the old login no longer working
- Use Penpot's built-in AI design tools, but only while a browser tab with the plugin stays open
What it can't, and why
- Use the AI (MCP) design tools without a browser openthe AI tools only run through a live browser tab with Penpot's plugin connected
- Export a design to an image file through the API alonethere is no documented way to do this outside the app or the browser-based AI tool
- Automatically update a design wherever a shared color/style value changesthe system saved the new value but did not update the shapes using it
1 more
- Sign up for or cancel a paid plan without using the websitethere is no way to buy or manage a subscription through the API
Can an AI agent sign up for Penpot on its own?
Yes, over the API, without a browser. prepare-register-profile + register-profile RPCs (documented in /api/_doc); no CAPTCHA
Does Penpot have an MCP server, and can an agent connect to it?
Yes. Penpot has an official MCP server. The server is hosted and lists 4 tools.
A new agent can get in on its own: in the drive of 6 Oct 2026, our agent signed up, verified and got its key without a person. Through the MCP server, 4 of our agent's 4 attempts worked.
What the drive found
APIOpenAPIMCP · official–CLI–SDKllms.txtWebhooks–SandboxHow does an AI agent get a Penpot API key?
In the drive of 6 Oct 2026, our agent got its Penpot API key over the API, without a browser or a person. create-access-token RPC with the login session; MCP key via create-access-token type mcp
Can an AI agent delete its Penpot account?
Yes, over the API, without a browser. delete-profile RPC -> 204 for both accounts; login then fails with wrong-credentials and the old token resolves to Anonymous User
Can an AI agent pay for Penpot?
Payment not reached.
Ways to pay found: In-app subscription page (checkout not observed).
It has a free plan.
What would let agents pay on their own
- Accept x402 or MPP on your API. Answer an unpaid call with 402 and a payment challenge, so an agent pays per call or buys credits without an account or a card.Step-by-step guide
- List your plans on Stripe Projects. Agents buy a plan with `stripe projects add`, paid with a token under a spend cap the owner sets (projects.dev).Step-by-step guide
No 402, x402, MPP, UCP or billing write API; not in the x402 Bazaar or mpp.dev. Subscription page offers Unlimited $7/user/month and Enterprise $25 with a 14-day free trial button; after CONTINUE we could not see the checkout or whether a card is needed. we did not see the checkout.
From the drive of 6 Oct 2026.
For the team behind Penpot.
Where agents stop in Penpot today, and the fixes that get them further, highest impact first.
The fixes, highest impact first
- Unblock the documented API path for agents
- Run MCP tools without an open tab
- Accept plain JSON in update-file
4 more fixes
- Apply token changes to the shapes using them
- Return clear 4xx errors
- Add a billing API for upgrades Step-by-step guide
- Publish a current, valid OpenAPI Step-by-step guide
- Claim it free and reply next to the result.
- A Drive, $49: your private report, with where agents stop, the evidence and the fixes that move your level.
- Fixed something? Order a Drive ($49) any time, or the Monthly drive ($29/month).
Details
Your API, MCP server or CLI is the product? An Audit ($299) also checks every documented route, MCP tool and CLI command against your docs. Compare plans.
Already claimed it? Open it in your dashboard.
Rather not be driven? Block AgentDrivesAgent in robots.txt or write to us. We stop driving it ourselves; this page stays, with its date.
Embed the badge on your site
Behind the level.
The part scores and the measures behind them.
Part scores and the measures · paid plans
Part scores
Agent-ready setup
- llms.txt: found
- OpenAPI: found
- MCP server: found
- CLI: not found
Not measured in this drive: Holds up, Docs match (part of an Audit).
Security: reported privately to the owner
The measures
- Work done57
- Reliability92
- Crash test–
Needs a paid plan
Not counted in the level. Our drive used free plan.
| Capability | Plan |
|---|---|
| Admin Console and SSO | Enterprise |
| SCIM and plugin allowlist | Enterprise |
| Audit logs | Enterprise |
For agents and builders.
The drive as data, every checkpoint and all 41 attempts.
How an agent connects · 5 tips
/api/tools/penpot.json/tools/penpot.mdMCP get_tool {"slug":"penpot"}
- Call https://design.penpot.app/api/main/methods/<command> with 'Authorization: Token <token>' and 'Accept: application/json'; the /api/rpc/command/ path from the guide may get a Cloudflare challenge
- Sign up via prepare-register-profile + register-profile, then verify-token with the token from the mail (it can take ~15 min)
- For update-file send application/transit+json when values must be keywords; give every shape full geometry; read revn/vern from get-file first
- export-binfile, import-binfile and clone-template reply as SSE: take the result from the 'end' event; omit the 'version' form field on multipart imports
- MCP: create-access-token {type:'mcp'}, enable MCP once under Your account > Integrations, keep a Penpot tab open on the file
Every checkpoint, in detail · 9 checkpoints
- DocsHeadlessIntegration guide, MCP guide, auto-generated RPC docs /api/_doc and OpenAPI /api/main/doc/openapi.json (3.0.0, 149 paths), penpot.app/llms.txt
- Sign upHeadlessprepare-register-profile + register-profile RPCs (documented in /api/_doc); no CAPTCHA
- VerifyHeadlessverification mail arrived about 13 min after sign-up (after a resend and a first check at ~11 min found nothing); verify-token RPC activated the account. The cause of the delay is unknown and may be on either side.
- KeyHeadlesscreate-access-token RPC with the login session; MCP key via create-access-token type mcp
- First callHeadlessget-profile with Authorization: Token on /api/main/methods/. The integration guide's curl path /api/rpc/command/get-profile gets a Cloudflare managed challenge (403 cf-mitigated: challenge).
- First actionHeadlesscreate-project and create-file RPCs, read back with get-project-files
- PayIn a browserNo 402, x402, MPP, UCP or billing write API; not in the x402 Bazaar or mpp.dev. Subscription page offers Unlimited $7/user/month and Enterprise $25 with a 14-day free trial button; after CONTINUE we could not see the checkout or whether a card is needed. we did not see the checkout.
- CancelNot neededNothing to cancel: our agent used the free plan.
- DeleteHeadlessdelete-profile RPC -> 204 for both accounts; login then fails with wrong-credentials and the old token resolves to Anonymous User
The attempt log · 41 attempts
| Capability | Route | Result | Evidence |
|---|---|---|---|
| Find docs: Find API, MCP and integration docs | api | done ✓ | help.penpot.app/technical-guide/integration (access tokens, webhooks, curl example), help.penpot.app/mcp/ (remote MCP at design.penpot.app/mcp/stream?userToken=), auto-generated RPC docs at design.penpot.app/api/_doc -> /api/main/doc (153 commands with param schemas), penpot.app/llms.txt 200 text/plain |
| Sign up: Register account headless via documented RPC prepare-register-profile + register-profile | api | done ✓ | POST /api/main/methods/prepare-register-profile -> 200 {token}; POST register-profile {token} -> 200 {id:7eed092c-..., email:the agent's inbox}. No CAPTCHA, no bot check met. Both commands are listed in /api/main/doc. |
| MCP discovery: POST server/discover (2026-07-28) to design.penpot.app/mcp/stream | mcp | done ✓ | server/discover -> HTTP 400 JSON-RPC -32000 'Bad Request: Server not initialized' (legacy). initialize offering 2026-07-28 -> 200 SSE protocolVersion 2025-11-25, serverInfo penpot 1.0.0, Mcp-Session-Id issued. tools/list without auth -> 4 tools: execute_code, high_level_overview, penpot_api_info, export_shape. tools/call without userToken -> 'No userToken found in session context. Multi-user mode requires authentication.' |
| Agent discovery files: Probe ai-catalog, agent-card, server-card, PRM, auth.md, robots, markdown | api | done ✓ | penpot.app/.well-known/ai-catalog.json, agent-card.json, agent.json, mcp/server-card.json, ucp: 404 (nginx). design.penpot.app/mcp/stream/server-card -> 406. design.penpot.app/.well-known/oauth-protected-resource -> SPA HTML 200 (not JSON); path-suffixed variant 301 -> /404. auth.md, SKILL.md 404. penpot.app/robots.txt: no Content-Usage/Content-signal lines; User-agent * Disallow /api/ etc. design.penpot.app/robots.txt: User-agent * Disallow /api/ /js/ /uploads/. penpot.app/llms.txt 200 (links llms-full.txt on penpot.dev); help.penpot.app/llms.txt 404. |
| Verify email: Receive Penpot verification mail and click link | api | failed | register-profile 200 at 02:58:09Z; re-sent via second prepare-register-profile+register-profile at 03:03Z (200, same profile id). inbox read the agent's inbox polled 02:58-03:13Z: 'no mail for the agent's inbox'. Inbox itself receives mail (earlier mails from other services present with --all). Mail not received; the cause may be on either side. |
| Log in: login-with-password before verification | api | failed ✓ | POST /api/main/methods/login-with-password -> 400 {"type":"validation","code":"wrong-credentials"} with the password just registered (account not yet verified) |
| Verify email: Receive Penpot verification mail and verify via documented verify-token RPC | api | done ✓ | Mail 'Verify your Penpot account' from no-reply@penpot.app (Date 03:10:59Z, token iat 02:58:09Z = first registration) read from inbox at ~03:16Z; POST /api/main/methods/verify-token {token} -> 200, then login-with-password -> 200 isActive:true |
| Get API credentials: Create personal access token via documented create-access-token RPC | api | done ✓ | POST /api/main/methods/create-access-token {name, expiration:'720h'} with session cookie -> 200 {id, token, expiresAt 2026-11-05}. First tries with expiration '30d' and 'P30D' -> 400 params-validation (explain names :expiration and schema duration; OpenAPI says only format: duration). |
| First authenticated API call: GET get-profile with Authorization: Token | api | done ✓ | GET /api/main/methods/get-profile with 'Authorization: Token ••••' -> 200 profile id 7eed092c-... email the agent's inbox |
| First authenticated API call (integration guide path): curl example from integration guide: GET /api/rpc/command/get-profile with token | api | blocked ✓ | GET and POST https://design.penpot.app/api/rpc/command/get-profile -> HTTP 403 cf-mitigated: challenge, 'Just a moment...' Cloudflare managed challenge, for our Web Bot Auth signed agent. The /api/main/methods/ path (the one in /api/_doc and OpenAPI servers) is not challenged. |
| First real action: Create a project and a design file in our team | api | done ✓ | create-project -> 200 id [id]; create-file -> 200 id [id] revn 0 |
| Create and edit vector designs: Add a board 'Home' with a rounded rect, then recolor and rename the rect | api | done ✓ | update-file add-obj (frame+rect) -> 200; mod-obj set fills/name -> 200; get-file revn 2 shows rect [id] name 'Primary Button' fills #E5484D inside board 'Home' |
| Build interactive prototypes: Add board 'Details', click->navigate interaction with dissolve on the button, and a flow starting at 'Home' | api | partial ✓ | update-file with JSON body: mod-obj set interactions -> HTTP 500 {type:server-error, code:assertion, explain: action-type must be one of #{:navigate ...}, value "navigate"} (JSON strings are not decoded to keywords inside set ops). Same change sent as application/transit+json with keywords -> 200; set-flow -> 200. get-file shows interactions [{eventType click, actionType navigate, destination Details}] and flow 'Main flow' startingFrame Home. |
| Comment on designs and reply: Open a comment thread on board 'Home', reply to it, resolve it, then list | api | done ✓ | create-comment-thread -> 200 id [id] seqn 1; create-comment -> 200; get-comments -> 2 comments with our ownerId and createdAt; get-comment-threads -> countComments 2; update-comment-thread-status isResolved -> 200 |
| Create reusable components: Make a 'Chip' main component and place a linked copy on board 'Home' | api | done ✓ | update-file (transit) add-obj main frame with componentId/mainInstance + add-component + add-obj copy with shapeRef -> 200. get-file: data.components has Chip (mainInstanceId [id]); copy [id] has componentId, componentFile, shapeRef -> main. Workspace in browser renders the main 'Chip' with the component icon and the copy in 'Home' (shots/008.png). |
| Define and sync design tokens: Create token set 'brand' with color.primary, apply it to the button fill, then change the token value | api | partial ✓ | set-token-set + set-token -> 200; get-file tokensLib shows brand.color.primary; mod-obj applied-tokens {fill: color.primary} -> 200; set-token value #E5484D -> #00AA55 -> 200 and tokensLib shows #00AA55, but the rect fills stay #E5484D in get-file and in the workspace render (shots/008.png). Token propagation to shapes is not done by the backend. |
| Build interactive prototypes: Check the API-made interaction fires in View mode | browser | partial | View mode (share link, section=interactions) shows flow 'Main flow' starting at Home and renders the button (shots/013.png); two clicks on the button in our agent's browser did not navigate to 'Details' (shots/015.png). Interaction is stored (get-file) but firing was not confirmed. |
| Share a view-only link: Create a share link for Page 1 and open it without a session | api | done ✓ | create-share-link -> 200 id [id]; anonymous get-view-only-bundle {fileId, shareId} -> 200 permissions type share-link canRead true isLogged false; the /#/view?...&share-id= URL renders the board in View mode (shots/013.png) |
| Register outbound webhooks: Register a team webhook and read it back; delivery not tested | api | partial ✓ | create-webhook to a URL that does not answer 2xx -> HTTP 500 {type: server-error, code: webhook-validation} (a validation error sent as 500); with https://agentdrives.com/ (our own site, answers 200) isActive:false -> 200 id [id]; get-webhooks lists it. Delivery not tested: we have no webhook receiver of our own in this drive and did not use a third-party catcher. |
| Create a team, invite members, assign roles: Create a team, invite our second inbox as editor, accept as that user, promote to admin | api | done ✓ | create-team -> 200 [id]; create-team-invitations [the agent's inbox, our own inbox] role editor -> 200; invitation mail arrived; invitee signed up via prepare-register-profile with invitationToken, verified, verify-token(invitation) -> 200 state created; get-team-members lists an inbox canEdit; update-team-member-role admin -> 204; get-team-members shows isAdmin true |
| Organize assets into shareable libraries: Publish the test file as a shared library and link it into a second file | api | done ✓ | set-file-shared isShared true -> 200; get-team-shared-files lists 'AgentDrives Test File'; create-file consumer [id]; link-file-to-library -> 200; get-file-libraries(consumer) returns 'AgentDrives Test File' (which holds component Chip) |
| Organize work into projects and files: Create a second project, move a file into it, rename the project | api | done ✓ | create-project -> 200 [id]; move-files [consumer file] -> 204; get-project-files on new project lists 'AgentDrives Consumer File'; rename-project -> 204; get-projects shows 'AgentDrives Archive (renamed)' |
| Manage personal account settings: Set profile language to en and read it back | api | done ✓ | get-profile before: lang ''; update-profile {fullname, lang en, theme default} -> 200; get-profile -> lang en |
| Start a file from a template: Clone the built-in 'wireframing-kit' template into our project | api | done ✓ | get-builtin-templates -> 10+ ids; clone-template {projectId, templateId wireframing-kit} -> 200 SSE progress (import v1/metadata..sobjects) then end; get-project-files lists 'Wireframing kit v1.1' [id]; get-file-summary shows 66 components |
| Export and import whole .penpot files: Export the test file as .penpot and re-import it into the second team | api | done ✓ | export-binfile {fileId, version 3} -> SSE, end event carries asset URI; download -> 200 application/zip 20165 bytes, 22 entries; import-binfile multipart into team 2 Drafts: with version=3 as a form field -> 400 params-validation (version must be integer 1|3, multipart gives string), without it -> SSE end with new file id [id]; get-file on it shows boards Home/Details, Primary Button, Chip main+copy and component Chip |
| Get MCP key: Create the MCP key via create-access-token type mcp and enable MCP | api | done ✓ | create-access-token {name, type: mcp} -> 200 type mcp; get-current-mcp-token -> token; Integrations page lists key 'agentdrives-mcp'. Enabling the MCP Server status was done in the browser (Your account > Integrations toggle; no documented API for the toggle). |
| Create and edit vector designs (MCP): Via remote MCP execute_code add a text and a circle to board 'Details', read back via API | mcp | done ✓ | remote MCP https://design.penpot.app/mcp/stream?userToken=•••• with the Penpot tab open in our agent's browser and plugin connected (File > MCP server, auto-connected after enabling): execute_code list shapes -> 8 names; execute_code createText+createEllipse appended to Details -> ids; get-file via REST shows 'MCP Text' (text) and 'MCP Circle' (circle) under 'Details'. Without an open tab: 'No Penpot instance connected for user token.' |
| Export layers/boards to image: Export board 'Home' as PNG via the MCP export_shape tool | mcp | done ✓ | export_shape {shapeId Home, format png} -> MCP image content, decoded PNG 1815 bytes, 400x300, shows the red button and the yellow chip (export_home.png) |
| Inspect a design for code/CSS handoff: Get CSS and measurements for 'Primary Button' | mcp | done ✓ | execute_code penpot.generateStyle([shape],{type:'css'}) -> CSS with left 40px, top 40px, width 160px, height 48px, background #E5484DFF, 8px radii; matches the values set via the API |
| Personal access tokens: Generate a token and use it in place of the password | api | done ✓ | create-access-token -> token; every later call in this drive (create-project, update-file, comments, teams, export/import) used 'Authorization: Token ••••' with no cookie; get-access-tokens lists it |
| Pay step: Probe agent payment rails and the upgrade path without paying | api | done ✓ | No 402 anywhere: x402./mpp./agents.penpot.app do not resolve; /.well-known/ucp -> 301 /404 (design) and 404 (penpot.app); OpenAPI has no x-payment-info; not found in the x402 Bazaar or mpp.dev/api/services. Billing API: only read calls (get-subscription-usage -> editors list; profile.subscription null). In the app, Your account > Subscription offers Unlimited $7/user/month and Enterprise $25 with 'TRY IT FREE FOR 14 DAYS'; the Unlimited button opens 'Apply Unlimited (trial)' with an editors count and CONTINUE; after CONTINUE our agent's browser came back to the subscriptions page, still Professional, and we could not see where checkout happens or whether a card is asked. |
| Clean up created data: Delete webhook, share link, MCP key, files, projects, second team | api | done ✓ | delete-webhook 204 (get-webhooks -> []), delete-share-link 204, delete-access-token 204, delete-file x4 204, delete-project x2 204, delete-team 204 (get-teams -> only Default). get-projects still listed the two deleted projects right after (soft delete, Penpot keeps deleted items recoverable for a period). |
| Cancel plan: No paid plan or trial was started | none | skipped ✓ | Account stayed on the free Professional plan (subscription page shows Professional; profile.subscription null); nothing to cancel |
| Delete account and data: Delete both accounts via the documented delete-profile RPC | api | done ✓ | delete-profile -> 204 for the invitee (session cookie) and for the main account (Authorization: Token). Afterwards login-with-password -> 400 wrong-credentials for both; get-profile with the old token -> 200 Anonymous User (token no longer valid). |
| Co-edit a file in real time: Two accounts editing one file live | none | skipped | Not tried: needs two live browser sessions at once; we had a second account (team invitee) but no time left in the drive budget. |
| Install and run plugins: Install a plugin in a file | none | skipped | Not tried separately for lack of time. The MCP server itself runs as a Penpot plugin in the open tab (File > MCP server), which did load and run in our agent's browser (MCP attempt). |
| Build a custom plugin: Load a custom plugin manifest | none | skipped | Not tried for lack of time; Plugins API used indirectly through MCP execute_code (penpot.createText, generateStyle). |
| Admin Console and SSO (Enterprise): Enterprise feature | none | plan_gated | Subscription page: Enterprise $25/org member/month lists 'Native SAML/SSO and full Audit Trail logging', 'Granular plugin whitelisting'; our account is on the free Professional plan |
| SCIM and plugin allowlist (Enterprise): Enterprise feature | none | plan_gated | Subscription page: Enterprise $25/org member/month lists 'Native SAML/SSO and full Audit Trail logging', 'Granular plugin whitelisting'; our account is on the free Professional plan |
| Audit logs (Enterprise): Enterprise feature | none | plan_gated | Subscription page: Enterprise $25/org member/month lists 'Native SAML/SSO and full Audit Trail logging', 'Granular plugin whitelisting'; our account is on the free Professional plan |
| Self-host Penpot: Docker install | none | skipped | no docker in the drive sandbox |
Also in Design.
CanvaL1Can't sign up on its ownPenpot vs Canva
FigmaL1Can't sign up on its ownPenpot vs Figma