Components MCP for AI tools

Petal Pro is the full SaaS app this is built for

Auth, billing, admin, and Claude Code integration included. One purchase, unlimited projects.

MCP server for AI coding assistants

If half your day is spent in Claude Code, Cursor, or Windsurf, you’ve probably noticed AI agents writing Phoenix HEEx don’t reach for petal_components. They invent raw Tailwind soup instead — because they don’t know the component API exists.

The Petal Components MCP server fixes that. It exposes every component’s schema (attrs, slots, defaults, allowed values, docs) to AI agents over the Model Context Protocol. With it installed, the AI asks the server “what attrs does <.button> take?” before writing markup, and produces idiomatic pc_* HEEx by default.

It’s open source, hosted on Fly, and the schemas auto-sync with the latest petal_components release on Hex.

Install

One command. Works in any directory.

claude mcp add petal --transport http https://mcp.petal.build/mcp

That’s it. Open Claude Code in any Phoenix project, ask it to build something, and it’ll start calling list_components and get_component on your behalf. The same MCP URL works with Cursor, Windsurf, and any other MCP-compatible client.

What you get

Two tools right now, more coming:

  • list_components — every component in the library with a one-line summary (attr count, slot count, required fields).
  • get_component — the full schema for a single component: attrs with types, defaults, allowed values, docs, plus all slots and a HEEx usage example.

Here’s what get_component returns for button:

# PetalComponents.Button.button/1

Phoenix.Component from `petal_components` v3.2.0.

## Usage

<.button> … </.button>


## Attributes

- `class` (:any) — CSS class
- `color` (:string) · default: `"primary"` · values: `primary`, `secondary`, `info`, `success`, `warning`, `danger`, `gray`, `pure_white`, `white`, `light`, `dark` — button color
- `disabled` (:boolean) · default: `false` — indicates a disabled state
- `icon` (:any) — name of a Heroicon at the front of the button
- `loading` (:boolean) · default: `false` — indicates a loading state
- `size` (:string) · default: `"md"` · values: `xs`, `sm`, `md`, `lg`, `xl` — button sizes
- `variant` (:string) · default: `"solid"` · values: `solid`, `light`, `outline`, `inverted`, `shadow`, `ghost` — button variant
...

## Slots

- `<:inner_block>`

The AI then writes markup that matches the real API, not whatever it guessed from training data three months ago.

How it works

The MCP server is a thin TypeScript service. It bundles a JSON snapshot of every component in petal_components. That snapshot is regenerated by a Mix script that introspects Phoenix.Component.__components__/0 on every PetalComponents.* module — so the schemas always match the actual library, no hand-maintained docs that drift.

When a new version of petal_components ships on Hex, the snapshot is regenerated and the server redeploys. The version is reported at mcp.petal.build/healthz so you can confirm what’s live.

Source code

Open source, MIT licensed: github.com/petalframework/petal-components-mcp.

Issues, PRs, and feedback welcome. If your favourite AI tool doesn’t support remote MCP yet, the same server has a stdio entry point — drop into the README for instructions.