-
Notifications
You must be signed in to change notification settings - Fork 0
fix(agents): Cloud Agent Figma REST file read #1034
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1598d3e
1b16fc6
00ce76e
0135ce0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| # Figma MCP auth on Cursor Cloud Agents | ||
|
|
||
| ## Incident | ||
|
|
||
| A Cursor Cloud Agent tasked with Figma work discovers the official Figma MCP | ||
| server (`https://mcp.figma.com/mcp`) in an `error` state: live tool discovery | ||
| fails and no Figma tools are available. Re-running Connect / OAuth from the | ||
| Cloud Agent cannot repair it. Desktop Cursor and the Cursor CLI remain able to | ||
| complete the same OAuth flow. | ||
|
|
||
| ## Live evidence (2026-08-16) | ||
|
|
||
| Unauthenticated `initialize` against the remote MCP endpoint: | ||
|
|
||
| ```http | ||
| POST https://mcp.figma.com/mcp | ||
| HTTP/2 401 | ||
| WWW-Authenticate: Bearer resource_metadata="https://mcp.figma.com/.well-known/oauth-protected-resource",scope="mcp:connect",authorization_uri="https://api.figma.com/.well-known/oauth-authorization-server" | ||
| ``` | ||
|
|
||
| Body: `Unauthorized`. | ||
|
|
||
| The same environment can reach Figma (`HEAD`/`POST` complete; no egress block). | ||
| `GET https://api.figma.com/v1/me` without a token returns | ||
| `{"status":403,"err":"Invalid token"}`. No `FIGMA_*` environment variables are | ||
| present on the Cloud Agent VM. | ||
|
|
||
| Figma's remote MCP is OAuth 2.1 with PKCE and an allowlisted MCP client | ||
| catalog. Cursor Cloud Agents are not a supported client for that catalog. | ||
|
|
||
| ## Decision | ||
|
|
||
| Do not treat Figma MCP as available inside Cloud Agents or Cloud Automations. | ||
| Cursor staff stated this explicitly: Figma MCP is not supported in Cloud agents; | ||
| it is fully supported in the IDE and the CLI (Neilson, 2026). There is no | ||
| estimated timeline; support is a joint Cursor/Figma change. | ||
|
|
||
| Use two disjoint auth paths: | ||
|
|
||
| | Surface | Auth | Capability | | ||
| |---|---|---| | ||
| | Cursor Desktop / CLI | Figma MCP OAuth (`Settings → Tools & MCP → Figma → Connect`) | Full MCP toolset (`get_design_context`, `use_figma`, write-to-canvas, …) | | ||
| | Cursor Cloud Agent | Figma personal or plan access token in `FIGMA_ACCESS_TOKEN` | REST only: `python3 scripts/ci/figma_rest_auth.py` then `python3 scripts/ci/figma_rest_file.py <file-key-or-url>` (`X-Figma-Token` only, pinned `https://api.figma.com/v1/me` and `/v1/files/{key}`) | | ||
|
|
||
| A personal or plan access token does **not** unlock Figma MCP on Cloud Agents. | ||
| It only authorizes the REST API. Do not commit the token. Do not put it in | ||
| `environment.json`, workflow YAML, or chat output. | ||
|
|
||
| Prefer a **plan access token** for organization Cloud Agent fleets | ||
| (admin-managed, expiry up to one year; Figma, 2026a). Use a personal access | ||
| token only when the operator is acting on their own account (maximum 90 days). | ||
| Both kinds are stored in the same secret name. Whoami and file bodies are | ||
| capped (64 KiB / 8 MiB). The opener refuses every header except | ||
| `X-Figma-Token` so a `Host` override cannot retarget TLS (CWE-22; MITRE, 2026). | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Host-header filtering is not CWE-22, and it does not retarget TLS after |
||
|
|
||
| ## Operator procedure | ||
|
|
||
| 1. **Desktop / CLI MCP (preferred for design-to-code).** In Cursor Desktop, | ||
| Settings → Tools & MCP → Figma → Connect, then Allow access in the Figma | ||
| browser window. Confirm with a Figma MCP `whoami` from a desktop agent. | ||
| 2. **Cloud Agent REST fallback.** In Figma: account menu → Settings → Security | ||
| → Personal access tokens → Generate new token. Name it for Cloud Agents. | ||
| Grant `file_content:read` (add comment scopes only if needed). Maximum | ||
| expiry is 90 days (Figma, 2025). Store the value as the Cursor environment | ||
| secret `FIGMA_ACCESS_TOKEN`. | ||
| 3. **Verify the secret without printing it:** | ||
|
|
||
| ```bash | ||
| python3 scripts/ci/figma_rest_auth.py | ||
| ``` | ||
|
|
||
| Success prints a handle/id/email line. Missing or rejected tokens exit | ||
| non-zero and never echo the secret. The helper opens a pinned | ||
| `http.client.HTTPSConnection("api.figma.com")` to `GET /v1/me` and refuses | ||
| any other URL, so Semgrep `dynamic-urllib-use-detected` does not apply | ||
| (`urllib.request.urlopen` is not used). | ||
| 4. **Read the file the buyer asked for.** Whoami is not file read. After the | ||
| secret verifies, run: | ||
|
|
||
| ```bash | ||
| python3 scripts/ci/figma_rest_file.py 'https://www.figma.com/design/<file_key>/<name>?node-id=12-34' | ||
| ``` | ||
|
|
||
| Or pass the file key and node id directly: | ||
|
|
||
| ```bash | ||
| python3 scripts/ci/figma_rest_file.py '<file_key>' --node-id 12:34 | ||
| python3 scripts/ci/figma_rest_file.py '<file_key>' --node-id 12:34 --images | ||
| ``` | ||
|
|
||
| The helper allowlists the file key (10-128 letters or digits) and node | ||
| ids before they enter the path, opens the same pinned | ||
| `api.figma.com` origin, and prints a token-free JSON outline (pages and | ||
| top-level frames at depth 2 by default). `--images` returns HTTPS PNG | ||
| URLs for those nodes. `file://`, `http://`, and `api.figma.com` locators | ||
| are refused. Use the outline or image URLs as the next design-to-code | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Use the outline or image URLs as the next design-to-code input" sends reconstructing agents into a dead end on this head. Say: outline is navigation until design fields are kept; |
||
| input; do not retry MCP Connect. | ||
|
|
||
| ## Why MCP Connect cannot be finished here | ||
|
|
||
| Figma only accepts MCP clients listed in its catalog (Figma, 2026b). The | ||
| Cloud Agent MCP client is not on that list, so the OAuth authorize endpoint | ||
| answers `Forbidden` / `401` before a browser grant can be created. Asking the | ||
| user to "click Connect" inside a Cloud Agent or Automation therefore cannot | ||
| succeed. The same Connect button works in the desktop IDE because that client | ||
| is allowlisted. | ||
|
|
||
| ## APA 7th references | ||
|
|
||
| Figma. (2025). *Changelog*. Figma Developer Docs. Retrieved August 16, 2026, | ||
| from https://developers.figma.com/docs/rest-api/changelog/ | ||
|
|
||
| Figma. (2026a). *Personal access tokens*. Figma Developer Docs. Retrieved | ||
| August 16, 2026, from | ||
| https://developers.figma.com/docs/rest-api/personal-access-tokens/ | ||
|
|
||
| Figma. (2026b). *Set up the remote server (recommended)*. Figma Developer Docs. | ||
| Retrieved August 16, 2026, from | ||
| https://developers.figma.com/docs/figma-mcp-server/remote-server-installation/ | ||
|
|
||
| Figma. (2026c). *Endpoints*. Figma Developer Docs. Retrieved August 16, 2026, | ||
| from https://developers.figma.com/docs/rest-api/file-endpoints/ | ||
|
|
||
| Fielding, R., Nottingham, M., & Reschke, J. (Eds.). (2022). *HTTP semantics* | ||
| (RFC 9110). Internet Engineering Task Force. | ||
| https://www.rfc-editor.org/rfc/rfc9110 | ||
|
|
||
| Hardt, D., Parecki, A., & Lodderstedt, T. (Eds.). (2025). *The OAuth 2.1 | ||
| authorization framework* (Internet-Draft draft-ietf-oauth-v2-1). Internet | ||
| Engineering Task Force. Retrieved August 16, 2026, from | ||
| https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1 | ||
|
|
||
| MITRE. (2026). *CWE-22: Improper limitation of a pathname to a restricted | ||
| directory ('Path Traversal')*. https://cwe.mitre.org/data/definitions/22.html | ||
|
|
||
| Neilson, K. (2026, June 10). Reply in *Figma MCP shows "Forbidden" in | ||
| Automations / Cloud Agents*. Cursor Forum. Retrieved August 16, 2026, from | ||
| https://forum.cursor.com/t/figma-mcp-shows-forbidden-in-automations-cloud-agents/162969 | ||
|
|
||
| Sakimura, N., Bradley, J., & Agarwal, N. (2015). *Proof Key for Code Exchange | ||
| by OAuth public clients* (RFC 7636). RFC Editor. | ||
| https://doi.org/10.17487/RFC7636 | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"so design-to-code continues" is not true of the default outline on this head. Changelog should say whoami + allowlisted file/nodes/images GET, then name the fields actually printed. Repair is #1043.