figma mcp无头认证
在无头环境中为Figma的模型上下文协议(MCP)绕过OAuth 2.1+PKCE身份验证。
为什么存在
Figma的MCP API需要OAuth 2.1身份验证,通常需要浏览器来完成授权流程。在无头环境(Docker容器、CI/CD管道、远程服务器)中,没有可用的浏览器。
此库实现了一种解决方法:
- 在Figma中动态注册OAuth客户端
- 为安全性生成PKCE挑战/验证器对
- 启动临时HTTP服务器以捕获OAuth回调
- 打印手动浏览器访问的授权URL
- 通过自动刷新在本地缓存令牌
运作原理
┌────────────────────────────────────────────────────────────────────────────┐
│ HEADLESS ENVIRONMENT │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 1. POST api.figma.com/v1/oauth/mcp/register │ │
│ │ → Dynamic client registration (RFC 7591) │ │
│ │ ← client_id + client_secret │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 2. Generate PKCE parameters │ │
│ │ code_verifier = random(32 bytes) → base64url │ │
│ │ code_challenge = SHA256(code_verifier) → base64url │ │
│ │ state = random(16 bytes) → base64url │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 3. Start HTTP callback server on port 9876 │ │
│ │ Listening on 0.0.0.0:9876/callback │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 4. Print authorization URL to stdout │ │
│ │ │ │
│ │ ══════════════════════════════════════════════════════════════════ │ │
│ │ FIGMA AUTH REQUIRED │ │
│ │ https://www.figma.com/oauth/mcp?client_id=...&state=... │ │
│ │ ══════════════════════════════════════════════════════════════════ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────┐
│ USER (manual) │
│ │
│ Copy URL → Open in browser │
│ → Authorize in Figma │
│ │
└────────────────────────────────┘
↓
┌────────────────────────────────┐
│ FIGMA │
│ │
│ Redirect to localhost:9876 │
│ ?code=XXX&state=YYY │
│ │
└────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────────────────────────┐
│ HEADLESS ENVIRONMENT │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 5. Callback server receives authorization code │ │
│ │ Validates state parameter to prevent CSRF │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 6. POST api.figma.com/v1/oauth/token │ │
│ │ Exchange code + code_verifier for access_token │ │
│ │ ← access_token, refresh_token, expires_in │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 7. Cache tokens to ~/.figma-mcp-tokens.json │ │
│ │ Includes client credentials for future refresh │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 8. Ready to call Figma MCP │ │
│ │ POST mcp.figma.com/mcp (JSON-RPC 2.0) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────────────┘代币生命周期
First run:
No cached tokens → Full OAuth flow → Cache tokens
Subsequent runs:
Load cached tokens
├─ Token valid (>1min until expiry) → Use directly
├─ Token expired → Attempt refresh
│ ├─ Refresh success → Update cache, use new token
│ └─ Refresh failed → Full OAuth flow
└─ No tokens → Full OAuth flow安装
npm install figma-mcp-headless-auth或者直接克隆:
git clone https://github.com/developerturtle/figma-mcp-headless-oauth.git
cd figma-mcp-headless-auth用法
程序化
const { getAccessToken, callTool } = require('figma-mcp-headless-auth');
async function main() {
// Handles full auth flow, caching, and refresh automatically
const token = await getAccessToken();
// Call any Figma MCP tool
const result = await callTool(token, 'get_design_context', {
fileKey: 'abc123',
nodeId: '1:2',
});
console.log(result);
}命令行界面
node index.js第一次运行将提示授权。后续运行使用缓存令牌。
码头工人
FROM node:20-slim
WORKDIR /app
COPY . .
EXPOSE 9876
CMD ["node", "index.js"]# Run with port mapping and token persistence
docker run -it \
-p 9876:9876 \
-v ~/.figma-mcp-tokens.json:/root/.figma-mcp-tokens.json \
figma-mcp-headless配置
| 环境变量 | 默认值 | 描述 |
|---|---|---|
FIGMA_OAUTH_PORT | 9876 | OAuth回调服务器的端口 |
FIGMA_TOKENS_PATH | ~/.figma-mcp-tokens.json | 令牌缓存文件的路径 |
API 参考
getAccessToken(): Promise
返回有效的Figma MCP访问令牌。自动处理:
- 正在加载缓存的令牌
- 刷新过期的令牌
- 需要时提供完整的OAuth流程
callTool(token, name, args): Promise
通过JSON-RPC调用Figma MCP工具。自动初始化MCP会话。
参数:
token-访问令牌来自getAccessToken()name-工具名称(例如。,get_design_context)args-工具参数对象
initSession(token): Promise
手动初始化MCP会话。返回会话ID。
可用的MCP工具
| 工具 | 说明 |
|---|---|
get_design_context | 提取设计数据并生成React/Tailwind代码 |
get_screenshot | 获取设计节点的PNG屏幕截图 |
get_metadata | 获取文件和节点元数据 |
get_figjam | 获取FigJam板数据 |
令牌缓存格式
{
"access_token": "fig_...",
"refresh_token": "fig_...",
"client_id": "...",
"client_secret": "...",
"expires_at": "2026-06-10T12:00:00.000Z"
}文件是通过以下方式创建的 0600 权限(仅限所有者读/写)。
安全
- PKCE(RFC 7636):防止授权码拦截攻击
- 状态参数:防止对回调的CSRF攻击
- 动态客户端注册:代码中没有硬编码凭据
- 令牌文件权限:仅限于所有者
故障排除
回调时“超时”
- 确保您的浏览器可以访问端口9876
- 检查防火墙规则
- 验证Docker端口映射是否在容器中运行
“注册失败”
- Figma API可能暂时不可用
- 检查网络连接
“令牌交换失败”
- 授权可能已被拒绝
- 状态不匹配(可能尝试CSRF)
令牌在Docker中不持久
- 装载令牌文件:
-v ~/.figma-mcp-tokens.json:/root/.figma-mcp-tokens.json
许可证
麻省理工学院许可证 - developerturtle
