You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I used the framesmith MCP from an AI agent (Claude Code) to design and ship a feature end-to-end: created a workspace, two projects, two canvases, a token design system, a preset, bound it into the repo, and ran the generate → evaluate → autofix loop.
The drawing API is good. The gap is onboarding — an agent has to learn framesmith's operating model by trial and error. I'd like a concise server instructions block and an idempotent init tool that binds the repo, scaffolds convention projects, and returns live IDs + a workflow cheatsheet + known gotchas. I also hit several concrete bugs (listed at the bottom).
What already works well
So this reads as constructive, not a teardown:
batch_design (the I/U/D/C/M/R op language) is expressive and fast.
The framesmith://guidelines resource is genuinely good — once you know to read it.
canvas_evaluate → canvas_autofix → re-evaluate is a great loop; autofix ops are paste-ready.
The workspace → project → canvas token-inheritance model is the right design.
canvas_bind (designs as checked-in JSON) is a great idea.
The core problem
Every painful moment was not knowing how framesmith works up front, not the API itself. A fresh agent connection has tool names and schemas, but no model of how to use them together. Things I only learned by hitting them:
The Workspace → Project → Canvas hierarchy and how to scope work to a repo (I first created a project under the wrong workspace).
That design tokens are a layered system (workspace → project → canvas) referenced via $name.
That you should read framesmith://guidelinesbefore drawing — nothing points you there.
The gotchas in the bug list below — each cost a round-trip or a wrong result.
Proposal
Add a server instructions block (highest leverage, lowest effort). Other MCP servers (e.g. pencil, grain) ship instructions that load into the client's context on connect; framesmith doesn't. ~20 lines would orient any agent with zero tool calls: the hierarchy + how to scope to a repo, the $token model, "read framesmith://guidelines first," and the gotchas below.
Detect/create a workspace bound to dir (runs canvas_bind if not bound).
Ensure convention projects exist (default: a foundations/style-guide project + a UI project — see Convention).
Optionally seed or detect a starter design system (tokens).
Return live state: resolved IDs, on-disk layout, a short workflow cheatsheet, and the gotchas.
Why a tool and not just docs: canvas_bindre-keys all IDs, so a doc's IDs are stale instantly. A tool returns current IDs, so the agent doesn't have to re-list everything to recover. It's the one call I'd want to make first, every session.
Fold the gotchas into framesmith://guidelines and add a one-liner to the relevant tool descriptions (screenshot, import_design_md, canvas_move, canvas_bind) to catch agents who never open the resource.
Convention: "Foundations + UI" projects
I adopted a Design System project (the style-guide canvas) + a UI project (all screens). I'd recommend it as the init default, with two adjustments:
Naming overlap. framesmith already has a design-system token layer at the workspace level, so a project named "Design System" actually means "the visual style-guide canvas" — subtly different and confusing. Prefer "Foundations" / "Style Guide", and have init print: "tokens live at the workspace layer; this project just visualizes them."
"UI" doesn't scale forever. One UI project gets crowded as screens multiply. Let init accept feature/area project names (Onboarding, Settings, …) with UI as the default catch-all, and recommend one canvas per screen/state.
Bugs / sharp edges found this session
gradient / shadow as CSS strings crash screenshot. Setting gradient: "linear-gradient(...)" or shadow: "0 1px 2px rgba(...)" on a node makes screenshot fail with Cannot read properties of undefined (reading 'map'), with no indication of the offending node. Parse these CSS forms, accept a structured form, or validate at batch_design time with a clear error naming the node.
canvas_move after a bind doesn't move the file. It updates server state + workspace.json, but the canvas JSON stays in the old project's directory, so the viewer shows the target project empty. I had to manually mv the JSON. Move should relocate the file (or index canvases by path in workspace.json).
import_design_md is lossy. With both a - name: value list and a markdown table, it only extracted spacing (and injected a default scale that didn't match my values); it returned colors: [], typography: [], radius: []. Component skeletons (button/card/badge) did import. Net: the design-system import can't carry most of a design system. Document the exact accepted schema or fix the color/type/radius parsers.
apply_preset clobbers canvas spacing. Applying a preset overwrote the canvas's spacing tokens with the preset's default scale (e.g. md: 16 vs my workspace md: 12), silently diverging from inherited tokens. Merge conservatively or warn on conflict.
canvas_evaluate flags exactly-4.5:1 contrast as failing. WCAG AA requires ≥ 4.5:1, so 4.5:1 passes. The check appears to use strict >, producing false-positive "critical" errors. Use >=.
canvas_bind re-keys every ID. After binding, IDs became repo-* and pre-bind IDs stopped resolving (… not found). Reasonable, but call it out loudly — and an argument for init returning fresh IDs.
screenshot of a specific nodeId failed with the same …reading 'map' error while full-canvas screenshot worked. Possibly related to the gradient/shadow bug; needs a clearer error.
Node-ID ergonomics. After a large batch_design, mapping returned IDs back to the variables I bound is error-prone (I mis-mapped once and edited the wrong nodes). Either return a { varName: nodeId } map from batch_design, or let U/D/M address nodes by the bound name within a session.
Suggested priority
Server instructions — biggest orientation win, trivial to add.
canvas_move not relocating the file, and the gradient/shadow crash — these produced wrong/empty results, not just friction.
init tool — consolidates onboarding + returns live IDs.
Summary
I used the framesmith MCP from an AI agent (Claude Code) to design and ship a feature end-to-end: created a workspace, two projects, two canvases, a token design system, a preset, bound it into the repo, and ran the generate → evaluate → autofix loop.
The drawing API is good. The gap is onboarding — an agent has to learn framesmith's operating model by trial and error. I'd like a concise server
instructionsblock and an idempotentinittool that binds the repo, scaffolds convention projects, and returns live IDs + a workflow cheatsheet + known gotchas. I also hit several concrete bugs (listed at the bottom).What already works well
So this reads as constructive, not a teardown:
batch_design(theI/U/D/C/M/Rop language) is expressive and fast.framesmith://guidelinesresource is genuinely good — once you know to read it.canvas_evaluate→canvas_autofix→ re-evaluate is a great loop; autofix ops are paste-ready.canvas_bind(designs as checked-in JSON) is a great idea.The core problem
Every painful moment was not knowing how framesmith works up front, not the API itself. A fresh agent connection has tool names and schemas, but no model of how to use them together. Things I only learned by hitting them:
Workspace → Project → Canvashierarchy and how to scope work to a repo (I first created a project under the wrong workspace).$name.framesmith://guidelinesbefore drawing — nothing points you there.Proposal
Add a server
instructionsblock (highest leverage, lowest effort). Other MCP servers (e.g. pencil, grain) shipinstructionsthat load into the client's context on connect; framesmith doesn't. ~20 lines would orient any agent with zero tool calls: the hierarchy + how to scope to a repo, the$tokenmodel, "readframesmith://guidelinesfirst," and the gotchas below.Add an idempotent
inittool:Safe to call repeatedly:
dir(runscanvas_bindif not bound).UIproject — see Convention).Why a tool and not just docs:
canvas_bindre-keys all IDs, so a doc's IDs are stale instantly. A tool returns current IDs, so the agent doesn't have to re-listeverything to recover. It's the one call I'd want to make first, every session.Sketch of the return value
{ "workspace": { "id": "repo-ws-…", "name": "Markdown Toolkit", "dir": ".framesmith" }, "projects": [ { "id": "repo-proj-…", "name": "Foundations", "dir": ".framesmith/foundations" }, { "id": "repo-proj-…", "name": "UI", "dir": ".framesmith/ui" } ], "designSystemLayer": "workspace", "workflow": [ "Design at the target width; reference tokens with $name.", "screenshot → review → iterate.", "canvas_evaluate (target >= 90) → canvas_autofix for mechanical spacing." ], "gotchas": ["gradient/shadow strings crash screenshots", "import_design_md only parses spacing", "…"], "guidelinesResource": "framesmith://guidelines" }Fold the gotchas into
framesmith://guidelinesand add a one-liner to the relevant tool descriptions (screenshot,import_design_md,canvas_move,canvas_bind) to catch agents who never open the resource.Convention: "Foundations + UI" projects
I adopted a Design System project (the style-guide canvas) + a UI project (all screens). I'd recommend it as the
initdefault, with two adjustments:initprint: "tokens live at the workspace layer; this project just visualizes them."initaccept feature/area project names (Onboarding,Settings, …) with UI as the default catch-all, and recommend one canvas per screen/state.Bugs / sharp edges found this session
gradient/shadowas CSS strings crashscreenshot. Settinggradient: "linear-gradient(...)"orshadow: "0 1px 2px rgba(...)"on a node makesscreenshotfail withCannot read properties of undefined (reading 'map'), with no indication of the offending node. Parse these CSS forms, accept a structured form, or validate atbatch_designtime with a clear error naming the node.canvas_moveafter a bind doesn't move the file. It updates server state +workspace.json, but the canvas JSON stays in the old project's directory, so the viewer shows the target project empty. I had to manuallymvthe JSON. Move should relocate the file (or index canvases by path inworkspace.json).import_design_mdis lossy. With both a- name: valuelist and a markdown table, it only extracted spacing (and injected a default scale that didn't match my values); it returnedcolors: [],typography: [],radius: []. Component skeletons (button/card/badge) did import. Net: the design-system import can't carry most of a design system. Document the exact accepted schema or fix the color/type/radius parsers.apply_presetclobbers canvas spacing. Applying a preset overwrote the canvas's spacing tokens with the preset's default scale (e.g.md: 16vs my workspacemd: 12), silently diverging from inherited tokens. Merge conservatively or warn on conflict.canvas_evaluateflags exactly-4.5:1contrast as failing. WCAG AA requires ≥ 4.5:1, so 4.5:1 passes. The check appears to use strict>, producing false-positive "critical" errors. Use>=.canvas_bindre-keys every ID. After binding, IDs becamerepo-*and pre-bind IDs stopped resolving (… not found). Reasonable, but call it out loudly — and an argument forinitreturning fresh IDs.screenshotof a specificnodeIdfailed with the same…reading 'map'error while full-canvasscreenshotworked. Possibly related to the gradient/shadow bug; needs a clearer error.batch_design, mapping returned IDs back to the variables I bound is error-prone (I mis-mapped once and edited the wrong nodes). Either return a{ varName: nodeId }map frombatch_design, or letU/D/Maddress nodes by the bound name within a session.Suggested priority
instructions— biggest orientation win, trivial to add.canvas_movenot relocating the file, and thegradient/shadowcrash — these produced wrong/empty results, not just friction.inittool — consolidates onboarding + returns live IDs.import_design_mdlossy, contrast>=— correctness.Filed from a real agent session designing a Chrome-extension side panel; happy to provide repro canvases or the full transcript.