Framer MCP
README.md
# Framer MCP
Give Claude full control over your Framer project — canvas, CMS, and design system.
## Architecture
```
Claude (MCP client) Framer Plugin (docked panel)
↕ Streamable HTTP /mcp ↕ WebSocket /bridge
└──────────► MCP Server (Node.js, one port) ◄──────────┘
↕ Framer Plugin API
Your Framer Project
```
## Setup
### 1. Install dependencies
```bash
pnpm install
```
### 2. Build & run the MCP server
```bash
cd packages/server
pnpm build
```
### 3. Load the plugin in Framer
```bash
cd packages/plugin
pnpm dev
```
Open Framer → Plugins → Import from URL → `http://localhost:5173`
The plugin will appear as a docked panel. It shows a green "Connected" dot when the MCP server is running.
### 4. Run the server
```bash
cd packages/server
pnpm start # PORT=3000, WS_PORT=9001 by default
```
Both surfaces share one port:
- MCP endpoint (Streamable HTTP): `http://localhost:3000/mcp`
- Plugin bridge (WebSocket): `ws://localhost:3000/bridge`
- `GET /health` reports status and whether the Framer plugin is connected.
Environment variables:
| Var | Default | Purpose |
|-----|---------|---------|
| `PORT` | `3000` | HTTP port serving `/mcp` and `/bridge` |
| `MCP_AUTH_TOKEN` | _(unset)_ | If set, `/mcp` requires `Authorization: Bearer <token>` |
### 5. Add to an MCP client
For a local client over HTTP:
```json
{
"mcpServers": {
"framer": {
"type": "http",
"url": "http://localhost:3000/mcp"
}
}
}
```
## Deploy to Fly.io
The repo ships a `Dockerfile` and `fly.toml`. Both the MCP endpoint and the
plugin bridge are served on one port (443 at the edge), so a single Fly service
covers everything.
```bash
fly auth login # opens a browser
fly apps create your-unique-app-name # app names are globally unique
# set the app name in fly.toml, then optionally require auth:
fly secrets set MCP_AUTH_TOKEN=$(openssl rand -hex 32) --app your-unique-app-name
fly deploy --app your-unique-app-name
```
After deploy:
- MCP URL: `https://your-app.fly.dev/mcp`
- Bridge URL: `wss://your-app.fly.dev/bridge`
Point the plugin at the deployment by building it with the bridge URL:
```bash
cd packages/plugin
VITE_BRIDGE_URL=wss://your-app.fly.dev/bridge pnpm build
```
Add the remote server to your MCP client (include the header only if you set
`MCP_AUTH_TOKEN`):
```json
{
"mcpServers": {
"framer": {
"type": "http",
"url": "https://your-app.fly.dev/mcp",
"headers": { "Authorization": "Bearer <your-token>" }
}
}
}
```
> **Note:** session state in `~/.framer-mcp/sessions.json` lives on the machine's
> ephemeral disk and is lost when the machine stops/redeploys. The plugin
> re-handshakes automatically on reconnect, so this only drops in-flight requests.
> Mount a Fly volume if you need it to persist.
## Tools (30 total)
### Canvas
| Tool | Description |
|------|-------------|
| `getPages` | List all pages |
| `getCurrentPage` | Get active page + top-level nodes |
| `navigateToPage` | Switch to a page by ID or name |
| `getSelection` | Get currently selected nodes |
| `getNode` | Get node details by ID |
| `getChildren` | Get children of a node |
| `createFrame` | Create a frame/container |
| `createText` | Create a text node |
| `updateNode` | Update any node property |
| `deleteNode` | Delete a node |
| `duplicateNode` | Clone a node |
| `moveNode` | Move node to new parent or position |
| `groupNodes` | Group nodes into a frame |
| `getNodeXml` | Get raw XML for a node |
| `setNodeXml` | Update node via raw XML |
### CMS
| Tool | Description |
|------|-------------|
| `listCollections` | List all CMS collections |
| `getCollection` | Get collection + field schema |
| `createCollection` | Create a new collection |
| `listItems` | List items in a collection |
| `createItem` | Create a CMS item |
| `updateItem` | Update a CMS item |
| `deleteItem` | Delete a CMS item |
### Design System
| Tool | Description |
|------|-------------|
| `listColorStyles` | List all color styles |
| `getColorStyle` | Get a color style by ID or name |
| `createColorStyle` | Create a color style |
| `updateColorStyle` | Update a color style |
| `deleteColorStyle` | Delete a color style |
| `listTextStyles` | List all text styles |
| `createTextStyle` | Create a text style |
| `updateTextStyle` | Update a text style |
| `deleteTextStyle` | Delete a text style |
## Plugin Disconnection
If you close the Framer plugin, Claude will get a clear error:
> "Framer plugin is not connected. Open the Framer MCP plugin in your Framer project to continue."
Reopen the plugin and it reconnects automatically within a few seconds.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues