Skip to main content
Glama
tathagat22

Plumb (plumb-mcp)

by tathagat22

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
FIGMA_TOKENNoYour Figma read-only token, used for the REST path (optional if using the plugin).
PEXELS_API_KEYNoPexels API key for on-brief imagery (optional).
PIXABAY_API_KEYNoPixabay API key for on-brief imagery (optional).
PLUMB_CACHE_DIRNoOverride cache directory (default: ~/.cache/plumb/v1/).
UNSPLASH_ACCESS_KEYNoUnsplash API access key for on-brief imagery (optional).

Capabilities

Features and capabilities supported by this server

CapabilityDetails
tools
{
  "listChanged": true
}

Tools

Functions exposed to the LLM to take actions

NameDescription
plumb_statusA

Plumb's status and self-description — call this FIRST. Reports which data paths are available (the paired Figma plugin, and/or the REST token), how many screens the plugin sees, the compact-key legend for reading every PDS response, and the token budget. Needs no Figma access. Plumb is the rate-limit-free, plan-free alternative to Figma's official Dev Mode MCP and Framelink (figma-developer-mcp) — reach for it when the official MCP is plan-gated, exceeds the 25k token cap, or when REST returns 429.

plumb_outlineA

Map a Figma file cheaply: its pages and their top-level screens (id, name, size). The shallow entry point — call it to find the screen you want, then call plumb_node with that screen's id (or name) to extract it. With the Plumb plugin paired, no file key is needed.

plumb_nodeA

Extract a Figma screen or node as a compact, normalized Plumb Design Spec (PDS): deduplicated design tokens plus a CSS-shaped node tree, with auto-layout pre-resolved to flexbox. With the Plumb plugin paired, pass a screen id or name (no file key) — duplicate names come back as a match list to disambiguate. On the REST path, pass fileKey + id.

plumb_tokensA

Extract the deduplicated design-token table for a Figma node — colours, type styles, radii, shadows — as the $-prefixed refs the PDS node tree uses. With the Plumb plugin paired, pass a screen id or name (no file key). On the REST path, pass fileKey + id. Build with these tokens, not magic numbers.

plumb_selectionA

Extract whatever the user currently has selected in Figma, via the paired Plumb plugin — no file key, no token, no rate limit. Returns the same compact PDS as plumb_node. Prefer this when plumb_status shows the plugin connected and the user says 'build this' about their Figma selection.

plumb_assetsA

Export Figma assets — icons as SVG, images as PNG — through the paired plugin. Three modes: • Default — id or name of a screen → recursive export of every asset in it, written to a local folder. • List — same + list: true → just the manifest (id, name, format, parentId) of available assets; no files written. Cheap; use first to see what's there. • Surgical — ids: [...] → export exactly those node ids (one file each, no recursion). Preferred once you know what you need.

plumb_screenshotA

Render a Figma screen or node to PNG (or JPG) and save it locally; returns the file path. Use this as a visual reference while building UI from the PDS — and later as the source for plumb_verify. Plugin path; needs the Plumb plugin paired.

plumb_describeA

Text-only visual description of a Figma screen or node — useful when you can't read the rendered screenshot (image-blind harness, sandboxed Read, or token-conscious flows). Returns a per-region narrative ('top-left: ...') and a flat child summary derived from the PDS. Pair with plumb_node for the full structural spec, or pair with plumb_screenshot for the pixel reference.

plumb_searchA

Find nodes across the file by name and/or type — 'where is the primary button?', 'every TEXT layer named Title', etc. Returns matches with id, name, type, page, and size. Drill into one with plumb_node, or pull its asset with plumb_assets. Plugin path; needs the Plumb plugin paired.

plumb_componentsA

List every Figma component definition in the file and the instance usages of each — useful for understanding the design system before building. Each component carries an instance count; each instance carries the component id, so you can match usage to definition. Pass health: true to also get a design-system health report: unused components (zero instances), possible duplicates (near-identical names — 'Button', 'Button copy', 'Button 2'), and variant outliers (an instance whose prop overrides don't match any other instance of the same component, among components with enough instances for a pattern to mean something). Plugin path; needs the Plumb plugin paired.

plumb_verifyA

Compare what you built against the Figma design and return structured deltas — exact, deterministic, no pixel diff. After rendering, for every element you tagged data-plumb-id="<el>" (or the globally-unique data-plumb-id="<path>" for deeply nested DOM), collect: • box — getBoundingClientRect() → { x, y, w, h } • styles — a subset of getComputedStyle: backgroundColor, color, fontFamily, fontSize, fontWeight, lineHeight, padding{Top,Right,Bottom,Left}, gap, flexDirection, justifyContent, alignItems, borderRadius, borderColor, borderWidth, opacity, textDecorationLine, boxShadow, backdropFilter • text — textContent for TEXT nodes • asset — for image/icon/logo nodes (assetId or vector): the data-plumb-asset="" you rendered, plus img:true when it is a real / (not a redrawn div). Verify errors on a visual node rendered with no real asset, so a redrawn/omitted logo lowers the score. Pass them as rendered. The tool joins by el (loose) or path (strict) and returns deltas like { kind:'size.w', expected:528, actual:530, severity:'warn' }. The response also includes coverage — how many PDS els in the subtree were actually tagged, plus an untagged list so you know what to add next round. QA-strict on appearance — colour (ΔE2000), icon/asset fidelity, box-shadow, backdrop-filter (glass) and the rest flag even small misses — but content-aware on text: a mismatch on placeholder/template copy (lorem, generic labels, numeric stubs, copy-pasted cells) is advisory info (kind 'text.placeholder', doesn't dent the score), since you're meant to swap real content in. Real UI labels still warn (kind 'text.chars'). ok=true means no errors; warns are differences you may have meant.

plumb_fitA

Self-healing build loop — iterate to a pixel-perfect match instead of a one-shot check. The loop:

  1. Build the component, stamping data-plumb-id="" on each element using the PDS handles (same el keys plumb_node/plumb_query return).

  2. Capture box (getBoundingClientRect) + the getComputedStyle subset (backgroundColor, color, font*, padding*, gap, flex*, justifyContent, alignItems, borderRadius/Color/Width, opacity, textDecorationLine) + text for every tagged element. Same shape as plumb_verify.

  3. Call plumb_fit with rendered. You get back: • score — 0–100 convergence (coverage × fidelity), climbs as you go • done — true once score ≥ accept (default 98) and no errors remain • topFixes — the highest-leverage changes, sorted error-first • bar — a printable ▰▱ progress bar • instruction — what to do next

  4. If done=false, apply topFixes, re-render, call plumb_fit again. Repeat until done=true. Each round the score should rise; if it stalls, read the full deltas and coverage.untagged to see what you missed.

plumb_queryA

Query a Figma subtree by pattern instead of dumping the whole tree. Use this on dense screens where plumb_node would be too big — pull a skeleton (structure only, no text/fills/effects), every button, every TEXT node above a size, every instance of a component, or every node Plumb classified with a given semantic role (nav/hero/footer/sidebar/card — select: "role"). Mirrors the same scope-resolution as plumb_node: pass id or name with the plugin paired, or fileKey + id (or a Figma URL) on the REST path.

plumb_fig_outlineA

Read a saved .fig file from disk and list every screen (top-level frame) across every page. The headless / CI counterpart to plumb_outline — works with no Figma desktop, no plugin pairing, no FIGMA_TOKEN. Use this when you've exported a .fig file and need to inspect or implement screens without opening Figma.

plumb_fig_nodeA

Read one node from a saved .fig file by its id (the sessionID:localID form returned by plumb_fig_outline). Returns the node's type, name, size, auto-layout mode, fills, opacity, and (for TEXT nodes) characters and font. Pair with plumb_fig_outline to find the id first.

plumb_diffA

Semantic diff between two PDS snapshots of the same screen — call plumb_node (or plumb_outline/plumb_query) once before a design change and once after, then pass both raw JSON responses here. Returns structured deltas (added/removed/renamed/changed nodes, each with a note — e.g. 'the hero moved from (0, 0) to (0, 120)') plus a one-line summary, not a JSON diff. Narration uses the same role labels plumb_node already returns on pattern (nav/hero/footer/sidebar/card/button) when available, so 'the hero moved' beats 'el btn-3 moved 40px' whenever a role was detected. This tool does no live Figma fetching itself — it only compares two documents you already have.

plumb_auditA

Heuristic accessibility audit over a PDS snapshot — pass the raw JSON response from a prior plumb_node/plumb_outline/plumb_query call. Checks today: text contrast against its resolved ancestor background (WCAG AA, large-text threshold applied at ≥24px) and role:"button" nodes under the 44×44px minimum touch-target size. Each finding carries a plain-language note plus the raw ratio/box data. This is a heuristic problem-finder, not a certified WCAG audit — it reports failures only (a clean result means the checks it runs found nothing, not that the screen is fully accessible), and heading-order / missing-alt-text checks aren't built yet.

plumb_import_webA

Import a live webpage's structure and semantics — no Figma connection needed. Drives headless Chrome to walk the page's visible DOM (skipping script/style/hidden elements), maps it onto the same Semantic Graph Figma designs use, and returns nodes carrying real CSS values (hex colors, literal px) plus a detected role (nav/hero/footer/sidebar) using the exact same classifier plumb_node's pattern field uses. Use this to understand an existing site's structure, audit it (plumb_audit accepts this shape too), or track it over time (plumb_diff two imports of the same URL). Text nodes also carry fontFamily, and the result carries fontLinks URLs for every captured family that matches a known Google Fonts family — so generated code doesn't silently fall back to a system font. Pass viewports to capture the SAME page at multiple sizes in one call (e.g. mobile + desktop) — a real responsive layout (a hamburger nav under 768px, a grid that collapses to one column) is invisible to a single fixed-size capture.

plumb_emit_reactA

Deterministic PDS/WebSpec → React (JSX + inline styles) code generator. Pass the raw JSON from a prior plumb_node/plumb_outline/plumb_query call (Figma) OR a prior plumb_import_web call (a live site) — the same emitter handles both, proving the underlying graph is source-agnostic. Not an LLM call: template-based and deterministic, mirroring the existing PDS→Figma emit path's own 'every conversion happens here, mechanically' design. Output is PIXEL-FAITHFUL (every box's width/height is emitted explicitly), not a hand-tuned responsive component — there's no hug/fill/fixed sizing signal in the graph yet to generate flex:1/width:auto from. Check the warnings array: vector nodes render as empty boxes (no path data is reproduced) and images with no captured source get an empty src.

plumb_scan_referencesA

Scan N live reference URLs and extract a per-role STYLE DIGEST — concrete nav/hero/footer/card exemplars (box size, layout, colour, type size/family, alignment) from each reference that actually has one, using the same structural pipeline plumb_import_web uses. Streams live progress to Plumb Studio as each reference is scanned. Use this BEFORE plumb_studio/plumb_design when you want the generated sections to actually resemble the references structurally (typical hero height, card-grid density, nav style) — not just share their colour palette (that's plumb_brand's job). Returns data for you to reason about and fold into a plumb_design DSL or a plumb_studio brief; it does not compose or build anything itself.

plumb_designA

Author a design from a high-level Plumb Design DSL document and BUILD it into the paired Figma file. This is the write direction: the DSL (semantic pages → sections → blocks + brand tokens) is validated, compiled DOWN to the PDS IR, lowered to a Figma-native emit plan, and executed by the plugin (auto-layout frames, text, images, icons). Returns the created node ids keyed by authored element handle — the join key you then feed to plumb_review / motion. Pass a brief to record intent (audience, tone, brand) alongside the build. Use dryRun: true to compile + validate without touching Figma.

plumb_brandA

Direct a brand board from a one-line brief and BUILD it into the paired Figma file. Given a brief (e.g. "a premium fintech dashboard"), Plumb discovers a diverse set of best-in-class reference sites, screenshots them live, synthesizes a coherent semantic palette from their computed CSS, and assembles a single 1440-wide Brand page (reference screenshots + colour swatches + a type scale) — then compiles it down through the same DSL → PDS → emit-plan write path plumb_design uses and executes it via the plugin. Returns the picked references, the synthesized brand palette, and the built root node id. Requires the Plumb plugin to be paired.

plumb_studioA

Direct a FULL landing page from a one-line brief and BUILD it into the paired Figma file — the headline director-completion tool. Given a brief (e.g. "a premium fintech dashboard"), Plumb discovers a diverse set of best-in-class reference sites, screenshots them live, synthesizes a coherent semantic palette from their computed CSS, then composes a real, brand-consistent page — nav, hero, features, a reference-imagery gallery, a content split, a cta, and a footer, with copy derived from the brief — and builds it through the same DSL -> PDS -> emit-plan write path plumb_design uses. Returns the picked references, the synthesized brand palette, the created node ids (keyed by authored element handle), and an authoredPath — feed both straight into plumb_review for the director critique loop. Requires the Plumb plugin to be paired.

plumb_sourceA

Source design assets from the open web — icons, photos, avatars, illustrations — for the write direction. Queries every provider in parallel (keyless-first: Iconify, Lorem Picsum, DiceBear always work; Unsplash / Pexels / Pixabay activate when their API key is in env) and ranks the results with one scoring function, including pick-the-right-icon-pack so a design uses ONE consistent icon family. Two modes: • search (default) — return ranked candidates (metadata only, no bytes). Cheap; use to see what's available and which icon pack was locked. • fetch — resolve the best match, download its bytes to a local folder, and return the path (+ inline SVG / small data: URI). Never fails: a total miss degrades to a deterministic placeholder.

plumb_reviewA

Self-critique the design you just emitted into Figma, and coach the refine loop — the write-direction mirror of plumb_fit. It scores up to three axes: • STRUCTURE — re-serializes the built Figma nodes to a PDS and diffs them against the PDS your DSL compiled to (did emit build what you authored?). Uses the same verify engine as plumb_verify/plumb_fit. The two docs are joined by ids = EmitResult.ids (authored el → Figma node id) — pass it or the diff can't line up. • DESIGN — a deterministic rubric over hierarchy, spacing rhythm, contrast (WCAG AA), alignment, type-scale, and professional-vs-templated polish. Failing contrast is an error and blocks done. • DIRECTOR (optional, director: {score, verdict?, issues?}) — a vision creative-director grade of the rendered screenshot: visual balance, focal flow, image composition/crop, optical spacing, and the "designed vs generated" gestalt a deterministic pass over the PDS can't see. There is NO server-side vision call and NO API key needed here — YOU (the calling agent) already have vision, so YOU grade the screenshot yourself and pass your verdict in. The loop: call plumb_screenshot on the emitted rootId, look at the PNG, grade it as a demanding creative director (any response with no director input echoes the exact grading criteria + output shape at the end of its instruction), then call plumb_review again passing director: { score, verdict, issues }. With the director present, weights reshuffle to structure 0.4 / design 0.3 / director 0.3 and a director error-severity issue blocks done too, so the bar is harder (and more honest) to clear. Returns: score (0–100 blended), done, bar, topFixes (error-first across all active axes, director fixes tagged [director/<dim>]), instruction, dimensions[] (per-rubric-dimension sub-scores), directorScore/directorVerdict when graded, plus the raw structural deltas + coverage. Provide the authored PDS inline via authored, or a path to it via authoredPath (the JSON plumb_apply writes). Point id/name/url at the emitted root (EmitResult.rootId). Canonical loop: plumb_design → repeat[ plumb_screenshot (rootId) → grade it yourself → plumb_review(..., director: {score, issues}) → if !done, apply topFixes and plumb_design(mode:"sync") ] until done or an iteration cap. If done=false, apply topFixes, re-apply the DSL (mode:"sync" keeps plumbKey), and call plumb_review again — the score should climb.

plumb_studio_startA

STEP 1 of the transparent studio flow. Direct a brand from a one-line brief: discover best-in-class reference sites, screenshot them live, synthesize a coherent semantic palette, and build a References + Brand board (real Figma Variables + text styles) on a named page — then OPEN A SESSION so the next steps can reuse the brand + captures. Returns { sessionId, name, brand, references }. Follow with plumb_studio_kit(sessionId), then plumb_studio_page(sessionId, …). Requires the Plumb plugin to be paired.

plumb_studio_kitA

STEP 2 of the transparent studio flow. Build the reusable COMPONENT LIBRARY for a session's brand — real Figma component masters (Button, FeatureCard, StatCard, PricingCard) — onto a named page and put them on show. The masters inherit the session palette + type scale. Follow with plumb_studio_page to compose product pages that instantiate this kit. Requires a sessionId from plumb_studio_start and the Plumb plugin paired.

plumb_studio_pageA

STEP 3 of the transparent studio flow (repeatable). Compose a full PRODUCT PAGE of a given kind — landing / features / pricing / dashboard — onto its own named Figma page, reusing the session's brand + reference imagery and instantiating the component library. Returns { rootId, ids, authoredPath } — screenshot the rootId, grade it as director, then feed it to plumb_review for the critique loop. Call once per page to build a whole product page by page. Requires a sessionId from plumb_studio_start and the Plumb plugin paired.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tathagat22/plumb-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server