Skip to main content
Glama
p1t42

figma-developer-mcp

by p1t42
README.md
# Figma MCP (personal access token)

Read-only Figma access for any MCP client, driven by your own PAT instead of per-client OAuth.
This folder is the single source of truth — `~/.config/figma-mcp` is a symlink to it.

## Layout

| Path | Purpose |
|---|---|
| `figma-mcp.sh` | stdio launcher (700). Every client points here, so no client config holds a secret |
| `env` | **your token** (600, git-ignored). The only place it exists |
| `env.example` | template. Never put a real token here — it is world-readable and not git-ignored |
| `package.json` / `package-lock.json` | pins the entire dependency tree |
| `node_modules/` | local locked install (git-ignored) |
| `assets/` | default download dir for `download_figma_images`; override with `IMAGE_DIR` in `env` |
| `../.mcp.json` | project-level MCP config at the `swe_projects` root |

Server: `figma-developer-mcp@0.13.2` (Framelink), Figma REST API, stdio transport.

## Token

Figma -> account settings -> **Security** -> *Personal access tokens*. Scopes:

- `file_content:read` — for `/v1/files/:key`, `/v1/files/:key/nodes`, `/v1/images/:key`
- `file_dev_resources:read` — Dev resources

Rotate by editing `env` only — no client config changes. Set an expiration when creating it: a PAT can read
**every file your account can access**, org-wide, with no per-file scoping.

## Hardening applied

- Token passed via env var, never a CLI flag, so it stays out of `ps` output.
- **Locked install** rather than `npx -y`: `package-lock.json` pins all 134 transitive packages, so
  dependencies cannot drift between runs. Reinstall with `npm ci`. (Pinning only the top-level version
  would still have let sub-dependencies resolve fresh on every launch.)
- **Telemetry off**: the package bundles PostHog with a hardcoded key. The launcher exports
  `FRAMELINK_TELEMETRY=off` and `DO_NOT_TRACK=1`.

## Client snippets

Replace `<REPO>` with the absolute path to this folder. These configs are read by different
runtimes and none of them reliably expand `~` or `$HOME`, so the path has to be spelled out.

**Standard `mcpServers` JSON** — Gemini CLI (`~/.gemini/settings.json`), Cursor (`~/.cursor/mcp.json`), VS Code, project `.mcp.json`:

```json
{
  "mcpServers": {
    "figma": {
      "command": "<REPO>/figma-mcp.sh",
      "args": []
    }
  }
}
```

**opencode** (`~/.config/opencode/opencode.jsonc`) — configured:

```jsonc
{
  "mcp": {
    "figma": {
      "type": "local",
      "command": ["<REPO>/figma-mcp.sh"],
      "enabled": true
    }
  }
}
```

**Claude Code** — registered at user scope:

```sh
claude mcp add figma -s user -- <REPO>/figma-mcp.sh
```

**Codex CLI** (`~/.codex/config.toml`) — untested, Codex not installed here:

```toml
[mcp_servers.figma]
command = "<REPO>/figma-mcp.sh"
```

## Smoke test

```sh
printf '%s\n%s\n%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"0"}}}' \
  '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| ./figma-mcp.sh
```

Expect `Figma MCP Server 0.13.2` and two tools: `get_figma_data`, `download_figma_images`.

Note: `grep -r` silently returns nothing under some sandboxes on this machine. Use
`find . -type f -exec grep -l PATTERN {} +` when sweeping for secrets.

## Limits

Read-only: file/node layout, styles, image asset download. Creating Figma files, Code Connect, and design
generation exist only in Figma's official server (`https://mcp.figma.com/mcp`), which is **OAuth-only** —
it does not accept personal access tokens — and only admits clients on Figma's MCP catalog.