⬡ FRAMEWERK
Integrations

Agents & MCP

Connect a coding agent to the Framewerk MCP server and have it generate a rendered screen.

View as Markdown

Agents & MCP

Status: shipped.

Framewerk is authorable by an agent. Connect a coding agent to the MCP server, give it one prompt, and it writes a spec you can render — no designer in the loop.

This page assumes the developer from the Introduction. It does not restate what a spec is.

Connect

The server speaks MCP over HTTP. Add it to your client's MCP config with the URL your instance exposes (cloud or local). On connect, the server returns instructions that include the skills install one-liner — the same command as on the Skills page — so the agent can teach itself the conventions before it writes anything.

Minimal client config shape (exact keys vary by client):

{
  "mcpServers": {
    "framewerk": {
      "url": "https://airframe.to/mcp"
    }
  }
}

Once connected, the agent has the Framewerk tools: read and write screens, components, styles, flows, and validate the result.

One prompt that produces a screen

Paste this into a session with the server connected:

Create a Framewerk spec with two screens. home has a column layout: a heading "Coffee Cart", a text node listing three drinks, and a primary button "Order" whose action is navigate(order). order has a heading "Order" and a button "Back" with action: back(). Give home a state variable oatMilk (boolean, default "false") and a badge content "Oat milk" with showWhen: "$oatMilk == true", plus a button that runs toggleState(oatMilk). Validate the document with validate() from @framewerk/spec and fix any errors before you finish.

The result is a document like this:

What the prompt produces
phone
SPEC.JSON
RENDERED OUTPUTFRAMEWERK RENDERER
Coffee Cart
Espresso · Cortado · Filter
Toggle oat milk
Order
Edit the JSON to update the rendered screen.Edits stay in this preview

Render it with the Quick Start host, or open it in the Playground.

Why validation matters here

Agents make two mistakes that look fine on screen: a navigate() to a renamed screen, and an action string that parses as nothing. Both are warnings from validate(), not errors. Run the validator in your loop and fail on warnings — the button will not tell you it is dead.

See Validation.