@particlesui/mcp-server
v1.2.7
Published
Particles UI MCP server — expose design tokens, impact analysis, and Figma component graphs to AI agents
Readme
@particlesui/mcp-server
The official Model Context Protocol server for Particles UI. It exposes your design tokens, semantic token search, change-impact analysis, WCAG contrast, named themes, Figma component graphs, docs & guidelines, releases, scalability score, coverage, and governance status to AI agents (Claude, Codex, Cursor, and any MCP-compatible client) — straight from the source of truth, so your tools reason about real tokens instead of pasted hex codes.
Most tools are reads. Four write tools (create_branch, create_token, update_token, delete_token) let an agent propose token edits — but only on a working branch: they obey the same governance as the Studio editor (a protected main is blocked, write-time policy is enforced, and a read-only access token can only read). Merging a change back into main stays a human review step in Studio.
Requirements
- Node.js ≥ 18 (only for the local stdio server — the remote endpoint needs no install at all).
- A Particles account on the Team plan or above — MCP access is enforced server-side. Calls from a lower plan return a clear "upgrade required" error.
- Credentials: a Studio access token or a CLI device token (see Authentication).
Two ways to connect
| | Setup | Best for |
| --- | --- | --- |
| Remote MCP endpoint | Point your client at https://api.particles-ui.com/v1/mcp with an Authorization: Bearer header. Nothing to install. | Most users — Claude Code, Codex, any Streamable-HTTP MCP client. |
| Local stdio server | Run npx -y @particlesui/mcp-server (or install it globally) as a local process. | Clients that only support local servers, air-gapped environments, or self-hosted backends. |
Both are authenticated the same way and expose the identical 44 tools.
Authentication
Two credential types work everywhere the server is used:
- Access token (
pat_…) — create one in Studio → Settings → Access Tokens → Create token. Org-scoped; can be restricted to specific projects or left set to all; permission level read or read-write (read covers the read tools; the four write tools need read-write). The secret is shown once at creation, so copy it immediately. Revoke it anytime from the same page; a revoked token fails closed on the next call. - CLI device token — if you've signed in with the Particles CLI, the local stdio server automatically reads the token
particles auth loginsaved to disk, so no env var is needed there.
npm install -g @particlesui/cli
particles auth login # device-auth flow; saves your tokenA CLI device token only works with the local stdio server (it reads the token from disk). The remote endpoint always needs an explicit
pat_…access token, passed as theAuthorizationheader (preferred) or, for header-less clients, a?token=query parameter (see Option 1). Neither credential stores a default project — setPARTICLES_PROJECT_IDyourself, or let the agent call thelist_projectstool (with no input it enumerates every organization the credential can access).PARTICLES_ORGANIZATION_IDoptionally pins id resolution to one organization; the remote/v1/mcpendpoint accepts the same as an?organizationId=URL parameter (Studio bakes it into generated connector URLs).
Option 1 — Remote MCP endpoint (recommended)
https://api.particles-ui.com/v1/mcpStreamable HTTP, authenticated with Authorization: Bearer pat_your_token_here.
Claude Code:
claude mcp add --transport http particles-ui https://api.particles-ui.com/v1/mcp \
--header "Authorization: Bearer pat_your_token_here"Or in .mcp.json:
{
"mcpServers": {
"particles-ui": {
"type": "http",
"url": "https://api.particles-ui.com/v1/mcp",
"headers": { "Authorization": "Bearer pat_your_token_here" }
}
}
}Codex (~/.codex/config.toml or a project-scoped .codex/config.toml):
[mcp_servers.particles-ui]
url = "https://api.particles-ui.com/v1/mcp"
bearer_token_env_var = "PARTICLES_TOKEN"Export PARTICLES_TOKEN=pat_your_token_here in the shell Codex runs from, or use a static header instead (avoid checking this form into version control):
[mcp_servers.particles-ui]
url = "https://api.particles-ui.com/v1/mcp"
http_headers = { "Authorization" = "Bearer pat_your_token_here" }Header-less clients (claude.ai, Claude Desktop custom connectors): some clients' "Add custom
connector" UIs only take a name and a URL — there's no field for a header. For exactly this case,
the remote endpoint also accepts the access token as a ?token= query parameter (the header wins
if a client sends both):
https://api.particles-ui.com/v1/mcp?token=pat_your_token_hereWith this form the URL itself is the secret — don't share screenshots or copies of it, and revoke the token from Studio → Settings → Access Tokens if it leaks. Prefer the header form above wherever your client supports headers.
Every tool takes a projectId. Agents that don't already know it should call list_projects first to discover project ids.
Option 2 — Local stdio server (fallback / air-gapped)
Install:
npm install -g @particlesui/mcp-serverInstalling globally lets your MCP client launch it by an absolute path, which is the most reliable setup for GUI clients (see the Connection closed note). The package provides a particles-mcp binary that speaks MCP over stdio. You can also run it with npx -y @particlesui/mcp-server without installing.
Set up your client (automatic — recommended)
The server can write the config for you. It uses absolute paths to the exact node and server file, so the Connection closed PATH problem can't happen:
particles-mcp setup # auto-detects installed clients (Cursor / Claude)
particles-mcp setup --client cursor --project <id> # target one client + set a default project
particles-mcp setup --print # just print the JSON snippet, don't writeIt merges into your existing config (preserving other servers) and backs up the file first. Then fully quit and reopen your client — MCP servers are spawned per session, so a reload isn't enough. The tools appear under particles-ui.
Flags: --client cursor|claude|claude-code|all, --project <id>, --token <token>, --api-base <url>, --print.
Manual config (reference)
If you'd rather edit by hand — Claude Code .mcp.json, Claude Desktop claude_desktop_config.json, Codex ~/.codex/config.toml, and Cursor ~/.cursor/mcp.json all take the same command / args / env shape (Codex's TOML form differs syntactically but carries the same fields):
{
"mcpServers": {
"particles-ui": {
"command": "npx",
"args": ["-y", "@particlesui/mcp-server"],
"env": {
"PARTICLES_TOKEN": "pat_your_token_here",
"PARTICLES_PROJECT_ID": "<optional default project id>",
"PARTICLES_ORGANIZATION_ID": "<optional default organization id>"
}
}
}
}# ~/.codex/config.toml
[mcp_servers.particles-ui]
command = "npx"
args = ["-y", "@particlesui/mcp-server"]
env = { "PARTICLES_TOKEN" = "pat_your_token_here", "PARTICLES_PROJECT_ID" = "<optional default project id>" }For GUI-launched clients prone to PATH issues (see Connection closed), use absolute paths to node and the installed dist/index.js instead of npx:
{
"mcpServers": {
"particles-ui": {
"command": "/absolute/path/to/node",
"args": ["/absolute/path/to/global/node_modules/@particlesui/mcp-server/dist/index.js"],
"env": { "PARTICLES_PROJECT_ID": "<your project id>" }
}
}
}Find the two absolute paths with which node and echo "$(npm root -g)/@particlesui/mcp-server/dist/index.js".
Configuration variables
| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| PARTICLES_TOKEN | Optional¹ | — | A pat_… access token, or a device-auth token. ¹Optional for the local server if you've run particles auth login; required for headless / CI / the remote endpoint's Authorization header. |
| PARTICLES_PROJECT_ID | Optional | — | Default project id used when a tool call omits projectId. Otherwise pass projectId per call (use list_projects to find one). |
| PARTICLES_API_BASE | Optional | https://api.particles-ui.com | Backend base URL — set this for a self-hosted Particles backend. Local stdio server only. |
Tools
44 tools, grouped by what they're for. The first group writes; the rest are reads.
Editing tokens (write)
| Tool | What it does |
| --- | --- |
| create_branch | Start a Change — a working branch forked from main — to edit on. The govern-first entry point for every write below. |
| create_tokens | Batch-create up to 200 tokens in one all-or-nothing call — use instead of many create_token calls when pushing a token set. |
| create_token | Create a token on a branch (pass its branchId; omit to target main, which protect_main may reject). Enforces write-time policy and tier ownership. |
| update_token | Update a token by its (branch-scoped) id — value, name, tier, description, scopes, group, or alias parent. Only the fields you pass change. |
| delete_token | Delete a token by id. Refused while other tokens alias it or a Figma component still binds it. |
| delete_tokens | Batch-delete up to 200 tokens by id, all-or-nothing. Dependents inside the batch don't block it; anything referenced from outside the batch fails the whole call. |
| create_theme | Create a named theme (dark, high-contrast, a brand variant) for a project — optionally on a mode axis other than the default 'theme' (light/dark) axis. |
| get_theme | Get a named theme and its full override set, each override resolved to the token name; includes the theme's mode axis. |
| set_theme_overrides | Point tokens at theme-specific values by token name (merge by default, or mode:"replace"). |
| delete_theme | Delete a named theme and its overrides (base token values are unaffected). |
Design-system structure (write)
| Tool | What it does |
| --- | --- |
| list_token_types / create_token_type / update_token_type / delete_token_type | Manage a project's token types (built-in + custom), each scoped to a tier. |
| list_token_groups / create_token_group / delete_token_group | Manage the sub-namespaces a token type is organized into. |
| list_platforms / create_platform / update_platform / delete_platform | Manage platforms (web/iOS/… targets) semantic tokens vary across in a multi-level project. |
| list_contrast_pairs / create_contrast_pair / delete_contrast_pair | Manage the foreground/background token pairs the accessibility gate checks (by token name). |
Tokens & search
| Tool | What it does |
| --- | --- |
| get_token | Get a token by name — resolved value, CSS variable, tier, and which Figma components use it. |
| find_tokens | Natural-language token search (e.g. "a calm background for cards"), ranked by relevance.¹ |
| resolve_theme | A token's resolved value within a single named theme on one mode axis (e.g. dark mode). |
| resolve_modes | The effective token set under a simultaneous multi-axis mode selection (e.g. {"theme":"dark","size":"small"} at once) — composes every named mode across its axis the way Studio and exports do. |
Impact & accessibility
| Tool | What it does |
| --- | --- |
| get_impact | Blast radius of changing a token — affected tokens, the Figma components that bind it, and accessibility risk. |
| check_contrast | WCAG contrast ratio between two tokens (AA / AA-large / AAA). |
Figma components
| Tool | What it does |
| --- | --- |
| get_component_graph | The full token-binding graph for a Figma component — part tree, every property→token binding, gaps, and stale bindings. |
| get_component_tokens | Flat list of the tokens a component binds, with per-property confidence. |
| list_components | All Figma components that bind tokens, with variants, token counts, and average confidence. |
Project navigation
| Tool | What it does |
| --- | --- |
| list_projects | Discover your projects — id, name, kind (foundation/brand/product), token mode, and description — so an agent can match a project a user names. Pass organizationId to enumerate an org; without it, returns the server's default project. |
| list_branches | A project's branches (id, name, whether main). |
| list_themes | A project's named themes (id, name, mode axis) on a branch; pass axis to filter to one mode group. |
| list_releases | A project's published releases (version, channel, branch, notes, createdAt), optionally filtered by channel. |
Docs & knowledge graph
| Tool | What it does |
| --- | --- |
| search_docs | Search design documentation pages by keyword or semantic intent — ranked results with page metadata.² |
| get_guidelines | Fetch a component's (or page's) usage guidelines as rendered markdown.² |
| get_neighborhood | Explore the knowledge-graph neighborhood around a token, component, or guideline entity.³ |
Scalability & governance
| Tool | What it does |
| --- | --- |
| get_score | A branch's Scalability Score (0-100): dedup health, alias coverage, naming health, and contrast pass rate, plus the raw counts behind each metric. |
| get_coverage | A project's rolled-up token coverage: latest Figma bound/unbound tokenization rate, latest code-usage scan total, and orphaned tokens. |
| get_governance_status | A project's governance health: flow metrics (merged changes, lead time, review coverage/latency, gate blocks, hotfix writes) over a trailing window, plus lifecycle hygiene (stale changes, suggested semver bump, unreleased changes). |
¹ find_tokens uses semantic ranking when embeddings are available for your project, and otherwise falls back to text matching. Embeddings are managed on the Particles side — nothing to configure here.
² search_docs and get_guidelines require the Team plan or above.
³ get_neighborhood requires the Business plan (knowledge graph explorer feature).
The component-graph tools read data the Particles Figma plugin produces by analyzing components; analysis itself isn't an MCP tool (it needs the Figma canvas).
Verify it works
Drive the local server by hand with the official MCP Inspector before wiring it into a client (after particles auth login):
npx @modelcontextprotocol/inspector \
node "$(npm root -g)/@particlesui/mcp-server/dist/index.js"It opens a UI where you can list the tools and call them against your real tokens.
Troubleshooting
MCP error -32000: Connection closed(stdio only) — your client couldn't launch the command. This is almost always a PATH problem: apps launched from the dock don't inherit your shell's PATH, so a bare"command": "node"/"npx"can't be found (common with nvm / fnm / Homebrew). Use absolute paths to bothnodeand the installeddist/index.js, as shown above. Avoid pointingcommandatnpxor theparticles-mcpbin — both rely onnodebeing on PATH.No Particles credentials found— runparticles auth login, or setPARTICLES_TOKENto apat_…access token.Authentication failed (401)— the token is missing, revoked, or expired, or the header is wrong. For the remote endpoint, confirm the exactAuthorization: Bearer pat_…header; for stdio, refreshPARTICLES_TOKENor runparticles auth loginagain.requires the Team plan or above— the project's organization is below Team; MCP access is gated.- No project selected — pass
projectIdon the call, setPARTICLES_PROJECT_ID, or calllist_projectsfirst to discover one. find_tokensreturns only text matches — semantic embeddings aren't available for that project/branch yet; results still work, just lexically.- Tools don't appear — confirm a valid token/header, then fully quit and reopen the client (not just reload).
License
See particles-ui.com for terms.
