Generative UI for LLMs · open source by Mobile Reality

MDMA: Markdown that mountsreal applications.

MDMA extends Markdown with interactive components defined in fenced ```mdma blocks. Give an LLM the spec and it returns structured, validated, renderable UI (forms, tables, approval gates) instead of a wall of text. Renders in React, Vue and React Native — and holds up on models small enough to run on open weights.

$ npm install @mobile-reality/mdma-renderer-react

Parse → validate → run → render

Four small packages take a markdown file the whole way to a live, stateful interface. Use the ones you need.

Parser
@mobile-reality/mdma-parser

Remark plugin: Markdown → MDMA AST.

Validator
@mobile-reality/mdma-validator

Static analysis, 17 lint rules, auto-fix.

Runtime
@mobile-reality/mdma-runtime

State, bindings, audit log, policies.

Renderer
@mobile-reality/mdma-renderer-react

React components for every block type.

And 8 more, of the 12 published
  • Vue rendererVue 3 renderer, same API surface as React.
  • Native rendererThe same documents as native iOS / Android UI.
  • AG-UI bridgeStream MDMA over AG-UI, route actions back.
  • Prompt packAuthor, fixer and agent prompts per model.
  • AttachablesHandlers for the stateful component types.
  • SpecZod schemas and types for every component.
  • CLImdma create (prompt builder) and mdma validate.
  • MCP serverServes the spec, prompts and docs to an LLM.

Every version, and what changed in it, is on the changelog.

Ten component types

MDMA defines ten interactive component types: form, button, tasklist, table, callout, approval-gate, webhook, chart, thinking, and custom. Each is a schema in the spec. Write its short YAML in an ```mdma block and the renderer for your framework turns it into a live, stateful element.

type: form

Typed fields, validation, sensitive flags.

type: button

Actions with optional confirm dialogs.

type: tasklist

Checklists with required items + onComplete.

type: table

Sortable columns over structured rows.

type: callout

Info / warning / error notices.

type: approval-gate

Role-based sign-off before proceeding.

type: webhook

Fire an outbound call on an event.

type: chart

Line / bar visualisations from inline data.

type: thinking

Render the model's reasoning trace.

type: custom

Your own component, registered by the host.

The tenth type is the escape hatch. A model cannot invent type: timer, but it can emit type: custom with name: timer once your host registers that variant — so your own components stay authorable by an LLM without ever changing the spec.

One document, three renderers

Parsing, state, bindings, policy and audit are headless — they live in the spec and runtime packages and never touch a view. So the same MDMA document renders in React, Vue 3 or React Native, and a theme object written for one works in the others.

React

@mobile-reality/mdma-renderer-react

The reference renderer. All ten component types, element overrides, custom variants and theming.

Vue 3

@mobile-reality/mdma-renderer-vue

Same public API, ported to provide/inject and composables. Ships the same styles.css, so a theme is portable.

React Native

@mobile-reality/mdma-renderer-react-native

Native iOS and Android UI from the same document. Shares the MdmaTheme token shape with the web renderers.

Theming

Pass theme="light", "dark", "auto" to follow the OS preference, or a full token object. The web stylesheet is driven by --mdma-* variables, so you can also override it in your own CSS. Button hover and focus rings derive from your palette instead of the built-in purple.

Streaming and agents

Blocks render as they stream, and a half-written fence shows a skeleton rather than an error. mdma-agui carries documents over the AG-UI protocol and routes submits, approvals, completed checklists and webhook triggers back into the agent run — including interrupts, so a run can pause on an approval gate and resume from the answer.

Edit the markdown. Watch it render.

This is the real @mobile-reality/mdma-renderer-react running in your browser. Change the source on the left.

document.md
rendered output
Parsing…

Talk to the MDMA Agent

Describe a component for your own use case: a contact form, a sortable table, an onboarding checklist, an approval gate. The agent renders it live in the panel on the right. Verify your email to start.

Loading interactive demo…

Same prompt. Different contract.

Ask an LLM to collect contact details. Without a spec you get prose you have to parse by hand. With MDMA you get a block you can render and validate.

Without MDMA: free-form text
Sure! To contact us, please provide the following information:

1. Your full name
2. Your email address
3. A message (at least a few sentences)

Once you've gathered those, you can send them over and
someone from the team will reply. Let me know if you'd
like me to format this as a list or a table instead!
With MDMA: a renderable block
# Contact us

Fill in the form below and we'll get back to you.

```mdma
id: contact-form
type: form
fields:
  - name: full_name
    type: text
    label: Full Name
    required: true
  - name: email
    type: email
    label: Email Address
    required: true
  - name: message
    type: textarea
    label: Message
    required: true
    validation:
      min: 10
      message: Please enter at least 10 characters.
onSubmit: submit-contact
```

```mdma
id: send-btn
type: button
text: Send Message
variant: primary
onAction: submit-contact
```

It has to work on the cheap model too

Everything works on a flagship. The question is what happens on the small, open-weights model you actually want in production. We ran four open-source generative-UI formats — each from its own published prompt, each scored by its own validator, auto-repair off for everyone including MDMA — and published every raw generation.

Rendered every single time

share of scenarios where all 5 repeats rendered

FormatOpus 5Gemma-4-26BDrop
MDMA94.4%94.4%0.0pp
OpenUI Lang83.3%55.6%27.8pp
json-render83.3%38.9%44.4pp
A2UI (AGenUI)38.9%*77.8%N/A

* A2UI's flagship figure is depressed by verbosity, not unreliability — 52% of its Opus 5 generations ran past the 8k output ceiling, so no drop can be read from that row. The report also discloses where A2UI's own validator disagrees with the harness.

The prompt is part of the bill

You pay for the system prompt on every single request, before the model writes a token.

  • OpenUI Lang5,172
  • MDMA5,910
  • json-render8,466
  • A2UI (AGenUI)19,689

How it was kept fair

  • Each format used its own published system prompt, unmodified.
  • Each format was scored by its own validator, not ours.
  • Auto-repair was switched off for every format — including MDMA's.
  • Byte-identical user message, no format hints, 5 repeats per scenario at temperature 0.7.
  • Every raw generation is committed, so you can re-score it yourself.
Read the full benchmark report

1107 generations · 0 API errors · 18 scenarios × 5 repeats × 3 model tiers, all through OpenRouter.

Built for the token bill

MDMA cuts token cost because it runs on small, cheap models. Strict JSON breaks on those models (one bad quote and the whole payload is unusable), so teams reach for the largest tier. MDMA uses forgiving Markdown that small models like Gemini Flash and Claude Haiku emit reliably, backed by a deterministic validator and an LLM fixer. See it live in the MDMA Agent demo.

Runs on small, cheap models

Markdown is forgiving where strict JSON is brittle. A small model that mangles a JSON quote sends the whole payload to the bin; the same model emits valid MDMA. That means fast, low-cost models like Gemini Flash and Claude Haiku, instead of always reaching for the largest tier.

Deterministic validator, free

MDMA ships a static validator — 17 lint rules and 6 auto-fix strategies — that runs without an LLM. Catching structural problems costs nothing per call, so you don't burn tokens re-asking the model to fix its own output.

LLM fixer for the rest

What the validator can't auto-fix goes to a fixer that repairs broken documents, and it works on the same small models, keeping the whole loop cheap.

What we eval

157 test cases · 11 suites · 36 tuned prompt variants

SuiteTestsWhat it asserts
Author33Correct component, exact field count, PII flags
Conversation30No regeneration on follow-up turns
Conversation flow6LLM-judged conversation quality
Custom prompt13Author + custom system prompt layering
Flows15Example flow custom prompts
Guidance15Calls the generate_mdma tool correctly
Guidance multiturn10Tool guidance held across turns
Guidance coexistence8MDMA alongside your own tools
Fixer16Repairs broken MDMA to valid output
Prompt builder10CLI prompt builder output
Isolated1Single failure-case iteration
Models in the eval matrix
  • OpenAI GPT-5.x / 4.1 (incl. mini, nano)
  • Claude Opus / Sonnet / Haiku / Fable
  • Gemini 3.x / 2.5 (incl. Flash, Flash-Lite)
  • Google Gemma (open weights)
  • xAI Grok 4.x
  • Our own fine-tuned MDMA-IL model

The eval suites run across all of these models; the same suites pass on the small, cheap tiers, not only the large ones. Each model gets its own tuned author and fixer prompt — 36 variants across five vendors. Run them yourself with the PromptFoo configs in mdma/evals, or see how the format holds up against other generative-UI formats in the cross-format benchmark.

How far down does it go

Far enough that we fine-tuned our own and published the weights. A 27B Gemma 4 fine-tune, served quantized, passes all 95 held-out cases in its gate. A model that size cannot hold a strict JSON UI contract together; it can emit MDMA. Read about the model.

Real use cases, shipped in the repo

Every example below is a working MDMA document in the open-source project, from a one-field form to a dual-approval compliance flow, built from the ten component types.

Examples

common use cases

Contact form

Collect a name, email and message, then submit. The simplest MDMA document.

formbutton

Budget approval

Submit a budget request, complete prerequisites, and gate it behind manager sign-off.

formtasklistapproval-gatecallout

Employee onboarding

Welcome a new hire through personal info, equipment selection and a manager checklist.

formtasklistapproval-gatecallout

Bug report

Capture reproduction steps and severity, with a triage checklist before submission.

formtasklistbuttoncallout

Customer survey

Structured post-support feedback with ratings, checkboxes and optional follow-up.

formcalloutbutton

Order tracking

Order status, shipment details and delivery milestones at a glance.

tablecharttasklistcallout

Sprint retrospective

Team metrics, feedback and action items captured from the sprint retro.

formcharttasklistcallout

Sales dashboard

Quarterly revenue trends, team breakdown and a sortable deals table.

charttabletasklistcallout

Feature request

A product request with business justification and a product-manager review gate.

formtasklistapproval-gatecallout

Job application

Apply with a resume and optional portfolio. Shows the file-upload field.

formbutton
Try it in the demo

Open the live demo and pick any example flow to run.

Blueprints

industry-specific workflows

Incident triage

Critical Ops

Assess severity, notify stakeholders, track resolution and gate closure behind sign-off.

formtasklistapproval-gatebuttoncallout

Change management

Engineering / Compliance

SOX/ISO release approval: risk assessment, dual approval and a pre-deploy checklist.

formtasklistapproval-gatecallout

Customer escalation

Customer Ops

SLA-aware escalation with sentiment tracking and a dynamic escalation-history table.

formtabletasklistbuttoncallout

Clinical procedure approval

Healthcare

Clinical + QA review and safety verification before a procedure is published.

formtasklistapproval-gatecallout

KYC case review

Finance / Compliance

Identity verification for KYC/AML: PII handling, document table and compliance approval.

formtabletasklistapproval-gate
Try it in the demo

Open the live demo and pick a blueprint flow to run.

Where MDMA fits

Between raw markdown and a hand-built JSON UI contract.

Raw MDCustom JSONMDMA
Renders as interactive UI
Readable as plain text
Schema-validatedpartial
LLM emits it reliablypartial
Stateful (bindings, audit)
No front-end build needed

Three ways in

Install the core once, then add the renderer for whatever you build in.

Developers

Parse and run MDMA documents, then render them with React, Vue or React Native.

$ npm install @mobile-reality/mdma-parser @mobile-reality/mdma-runtime
$ npm install @mobile-reality/mdma-renderer-react
$ npm install @mobile-reality/mdma-renderer-vue
$ npm install @mobile-reality/mdma-renderer-react-native

AI authoring

Give an LLM the prompt pack — it carries a tuned variant per model — or build prompts with the CLI.

$ npm install @mobile-reality/mdma-prompt-pack
$ npx @mobile-reality/mdma-cli

Agents

Stream documents over the AG-UI protocol and route submits, approvals and webhook triggers back into the run.

$ npm install @mobile-reality/mdma-agui

Frequently asked questions

What is MDMA?
MDMA (Markdown Documents with Mounted Applications) extends Markdown with interactive components defined in fenced mdma code blocks. A regular Markdown file becomes an interactive application with forms, tables, charts, approval gates and more.
How is MDMA different from raw markdown or a JSON UI contract?
Raw Markdown renders as text and a custom JSON UI contract is brittle on smaller models. MDMA is forgiving Markdown that small, cheap models emit reliably, and it is schema-validated so the output is renderable and safe. In a cross-format benchmark, MDMA rendered every time in 94.4% of scenarios on both a flagship model and an open-weights one, a 0.0pp drop between the two tiers.
Why does MDMA save on tokens?
Because MDMA works on small, cheap models such as Gemini Flash and Claude Haiku where strict JSON often breaks. A deterministic validator with 17 lint rules and 6 auto-fix strategies, plus an LLM fixer, keeps the loop cheap — so you don't burn tokens re-asking a large model to repair its own output.
Which components can MDMA render?
Ten types: form, button, tasklist, table, callout, approval-gate, webhook, chart, thinking, and custom. The custom type is a stable envelope your host fills in with its own components, so you can extend the catalog without changing the spec — and an LLM can still author them, because it emits type: custom with a registered name rather than inventing a new type.
Which frameworks can render MDMA?
React, Vue 3 and React Native, via @mobile-reality/mdma-renderer-react, @mobile-reality/mdma-renderer-vue and @mobile-reality/mdma-renderer-react-native. Parsing, state, bindings, policy and audit are headless, so all three share the same core and the same MdmaTheme token shape.
Which packages does MDMA ship?
Twelve packages under @mobile-reality/mdma-*: the spec, parser, validator, runtime and attachables-core, three renderers (React, Vue, React Native), an AG-UI bridge, a prompt-pack, a CLI and an MCP server.
Can I use MDMA with an agent framework?
Yes. @mobile-reality/mdma-agui bridges MDMA and the AG-UI protocol: documents stream in over inline text or a dedicated custom event, user actions (submit, approve, deny, completed checklists, webhook triggers) route back into the agent run, and interrupts let a run pause on an approval gate and resume from the answer.
Is there a model fine-tuned for MDMA?
Yes. MobileReality/mdma-gemma4-26b-dsl-unsloth-v1 is a 27B Gemma 4 fine-tune, published on Hugging Face under Apache 2.0, that reads a compact MDMA-IL DSL intent and returns a valid MDMA document. The LoRA is merged into the base weights, and the model passes all 95 cases in its held-out gate plus the standard author, flows, fixer, guidance and custom-prompt suites.
Is MDMA open source?
Yes. MDMA is MIT-licensed and maintained by Mobile Reality. The source is on GitHub at github.com/MobileReality/mdma.
Does MDMA work with Claude, GPT and Gemini?
Yes. MDMA is model-agnostic: any LLM that can write Markdown can emit MDMA. The prompt-pack ships 36 tuned author-prompt variants across OpenAI, Anthropic, Google, xAI and our own fine-tuned model, so the format works on small, cheap tiers rather than only the largest ones. An MCP server serves the spec, prompts and docs straight to an LLM.
How do I render MDMA in React?
Install @mobile-reality/mdma-renderer-react along with the parser and runtime, parse the markdown to an AST, create a document store, and pass them to the MdmaDocument component. It renders every component type as a live, stateful element. Add a theme prop for light, dark, auto or your own tokens.