Skip to main content
Glama
MarlonJD

DesignPort

by MarlonJD
README.md
# DesignPort

Free, local-first Figma MCP for AI coding agents — read, create and edit designs without a Figma API token or paid MCP access.

DesignPort gives Codex, Claude Code and Cursor both a PNG visual reference and structured design context: hierarchy, layout, typography, tokens, components and interactions. One MCP process connects to the Figma Plugin API through a local WebSocket bridge. DesignPort does not generate framework code; the agent implements the design using the target repository's own stack.

```text
Codex / Claude Code / Cursor
            │ MCP over stdio
        DesignPort
            │ WebSocket on localhost:5514
      Figma plugin
            │ Figma Plugin API
      Open design file
```

## Start from this checkout

Requires Node.js 22 or later and Figma desktop to import the development plugin.

```sh
npm ci
npm run build
```

In Figma, choose **Plugins → Development → Import plugin from manifest…**, select `plugins/figma/manifest.json`, and run **DesignPort Figma** in the document you want the agent to use. Keep the plugin running.

Register the built server with one command from the repository root:

```sh
codex mcp add designport -- node "$PWD/dist/src/index.js"
```

[Codex MCP setup](https://learn.chatgpt.com/docs/extend/mcp). For [Claude Code](https://code.claude.com/docs/en/mcp):

```sh
claude mcp add --transport stdio designport -- node "$PWD/dist/src/index.js"
```

For [Cursor](https://cursor.com/docs/mcp), add this to `.cursor/mcp.json`, replacing the path:

```json
{
  "mcpServers": {
    "designport": {
      "command": "node",
      "args": ["/absolute/path/to/designport/dist/src/index.js"]
    }
  }
}
```

The MCP client starts the server and bridge together. Use one client process on port 5514 at a time. Call `figma.status` to check the connection. Multiple open Figma documents require an explicit `sessionId` from that response.

The npm package and Community listing are **release pending**. Once the npm package is published, the equivalent Codex setup is `codex mcp add designport -- npx -y designport@1.0.0`. The package includes the Figma plugin files.

## Eight public tools

| Tool | Purpose |
| --- | --- |
| `figma.status` | Connections, capabilities, bounded recent events and limits. |
| `figma.get_context` | DesignIR, tokens, layout, component properties and overrides, internal audit/graph and matching PNG. |
| `figma.get_asset` | Bounded original or rendered asset bytes from a capture. |
| `figma.create_nodes` | Native frame, text, rectangle, component and local instance trees with Auto Layout. |
| `figma.update_nodes` | A distinct patch per node: text, typography, geometry, parent, layout, fills, strokes and exposed instance text properties. |
| `figma.delete_nodes` | Explicit captured subtree deletion. |
| `figma.clone_nodes` | Subtree cloning with destination parent, name and position. |
| `figma.set_prototype` | Bounded instant on-click navigation and named flow starts. |

There are no legacy tool aliases. Version 1.0 removes Adobe XD, provider adapters, `design.*` tools and delta responses. Audit and graph remain part of context, without separate tools. FigJam connectors, remote component imports, variant authoring and annotation workflows are outside the current scope.

## Read, then write

1. Use `figma.get_context` for `selection`, `screen`, `page` or `document`. PNG is included by default for non-document scopes; use `includeVisual: false` for properties alone.
2. Inspect `properties.snapshot.complete`, coverage and omissions. A paginated or budget-incomplete capture cannot authorize a write.
3. Pass `properties.snapshot.id` as `expectedSnapshotId` and `properties.snapshot.identity.sessionId` as `captureSessionId`. The separate `sessionId` selects the bridge connection.
4. Send explicit node IDs. Update targets and destination parents must be captured; delete and clone require all descendants in scope. Selection changes do not redirect a write.
5. Read fresh context after each write or mutation failure. Writes are serialized and invalidate the previous snapshot immediately.

Creation is limited to 256 specifications, 32 roots and depth 12. Update and delete accept at most 100 targets; clone accepts 32 roots. Expanded instance creation and subtree operations are limited to 2000 native nodes. PNG/JPEG input is limited to 4 MB per image, 4096 pixels per side and 16 million pixels. Prepared write requests are capped at 8 MB.

Create and clone clean up task-created nodes on failure. Update and prototype operations attempt native rollback. Unexpected deletion failures report exactly which IDs were removed; deletion is not a database transaction. Figma's normal Undo remains available.

See [examples](EXAMPLES.md), the [DesignIR guide](DESIGN_IR.md) and the [security boundaries](SECURITY.md).

## Configuration

| Variable | Default |
| --- | --- |
| `DESIGNPORT_HOST` | `127.0.0.1` (loopback only) |
| `DESIGNPORT_PORT` | `5514` |
| `DESIGNPORT_REQUEST_TIMEOUT_MS` | `30000` |
| `DESIGNPORT_PAIRING_TOKEN` | `designport-local-pairing` |

The plugin's WebSocket URL and pairing value must match the server; edit `plugins/figma/ui.html`, `code.js` and the manifest together for a custom port or pairing value. The bundled pairing value is public, not a secret. No Figma REST token is involved. Design data stays between the plugin, local server and your configured coding agent; that agent may send context to its model provider.

The plugin uses Figma's required `dynamic-page` manifest and async APIs. It explicitly loads all pages before subscribing to document changes so external edits invalidate snapshots. Large files can take longer to initialize.

## Verify and package

```sh
npm test
npm run typecheck
npm run build
node --check plugins/figma/code.js
npm run test:package
npm run package:plugin
```

`test:package` creates `artifacts/designport-1.0.0.tgz`, installs it in a clean temporary directory without development dependencies, checks the real stdio tool surface and shutdown, then removes the temporary install. `package:plugin` prepares `artifacts/figma/`; supply `-- --id FIGMA_ASSIGNED_NUMERIC_ID` when preparing an actual Community submission. [Release instructions](docs/RELEASING.md) distinguish local verification from publication.

`npm run smoke:figma -- --document-name "Your scratch document"` runs the create/image/clone/edit/delete scenario in a named scratch file and saves PNG evidence. `npm run fixture:avia -- --port 5514` exercises the three-screen fixture in its explicitly named scratch document. Run `npm run visual:compare -- reference.png candidate.png --json` for local PNG comparison.

DesignPort is licensed under GPL-3.0-or-later. This implementation uses no copied Grab source.

TDQS

B3.2/5.0

Scored across 13 tools

Disambiguation3/5

Several tools overlap: get_selection_context and export_ir both return DesignIR, get_visual_context and get_design_context both include PNG, and get_design_context duplicates generate_code's code output. Descriptions clarify some boundaries, but an agent could easily struggle to choose between the composite get_design_context and the more specific tools.

Naming Consistency5/5

All tools share a consistent design. prefix and use a clear verb-first snake_case pattern: list, get, export, generate, create, update, ping. The naming is predictable and easy to navigate.

Tool Count5/5

13 tools is a well-scoped set for a design bridge covering host discovery, context retrieval, IR export, code generation, and mutation actions. Each tool serves a distinct workflow step without unnecessary bloat.

Completeness4/5

The surface covers the core design-to-code journey: reading selection/screen context, getting visuals, exporting IR, generating code, and creating/updating design artifacts. Some operations like listing all screens/components or deleting/updating components are missing, but agents can still complete primary workflows.

Maintenance

ActivityMaintained
ResponsivenessNo issues