# HUXForm

> HUXForm is a generative human-experience runtime for AI agents

- **Type:** MCP server
- **Install:** `agentstack add mcp-agiwhitelist-huxform`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [agiwhitelist](https://agentstack.voostack.com/s/agiwhitelist)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [agiwhitelist](https://github.com/agiwhitelist)
- **Source:** https://github.com/agiwhitelist/HUXForm
- **Website:** https://agiwhitelist.github.io/HUXForm/

## Install

```sh
agentstack add mcp-agiwhitelist-huxform
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

### See it run

**[▶ Full-resolution video](./demo/huxform-demo.mp4)** · [12 hero stills](./demo)

> **About the demo.** The 80-second clip above is a deterministic HTML/CSS
> render of one audit run, kept reproducible for the README. A live HUXForm
> run varies in its visual metaphor — the Director may draw the same security
> audit as a ledger, an inspection station, or a console, and that variety is
> the point. The tool calls, the OSV/GHSA vulnerability data, and the MCP
> discovery flow shown are all real.

> **HUXForm is a runtime for generative software.**
> You describe a task in one sentence. HUXForm **directs** a one-off visual
> concept for it, **researches** the task with real tools (web search, fetch,
> MCP servers, CLI, OpenAPI), **generates** a self-contained mini-app on the
> fly, **streams** it onto the stage as the model draws it, and gives it a
> safe bridge to call tools back — including the ability to **redesign
> itself** mid-conversation.

Not a chat. Not a dashboard kit. Not a component library. Not a wrapper
around someone else's UI. **Every task gets a custom piece of software,
with real data, and that software is allowed to rewrite itself.**

```text
Intent
  → Director (plan + visual brief)
  → Researcher (real tool calls: web.search, web.fetch, mcp.*, files.read…)
  → UI Generator (streaming HTML/CSS/JS, watch it being drawn)
  → Sandboxed stage + bridge (the app calls tools; can also self-redesign)
  → Mission loop (optional: chain N turns toward one bigger goal)
```

### Five things almost no other AI tool ships

| # | Capability | Why it matters |
|---|-----------|----------------|
| 1 | **Generative UI, not a template** | The Director commits to a metaphor (a meteo station, a field notebook, a podium ceremony, a sonar sweep) **before any code is written**, with banned defaults. The UI Generator treats the brief as a constraint. Outputs converge to a one-off mini-app, never to "another dashboard". |
| 2 | **Real data, not hallucination** | A server-side **Researcher** ReAct loop calls live tools (DuckDuckGo, optional Tavily/Brave/Serper, MCP servers, attached files) until it has facts. The codegen prompt forbids inventing numbers; the iframe receives `agui.research` as ground truth. |
| 3 | **Streaming codegen** | The LLM streams HTML tokens. HUXForm injects the partial document into the iframe via `srcDoc` every ~120 ms — **you watch the app being designed live**: palette appears first, then the title, then sections fill in, then SVG details. On `ui_ready` the live, bridge-wired version swaps in. |
| 4 | **Self-evolving UI** | From inside the iframe, a generated app can call `await agui.evolve("show me the same data as a sparkline grid")`. HUXForm regenerates the document around the existing task state and the iframe swaps to the new shape. The interface stays alive instead of accumulating dead toggles. |
| 5 | **Live tool discovery + audited install** | `tools.discover` ranks candidates from npm `@modelcontextprotocol/*` + GitHub `topic:mcp-server`. `audit_top=N` reads each top candidate's README and asks an LLM to classify permissions, surface red flags ("ZIP extraction → path traversal") and compute a trust score. `tools.install` is approval-gated **every time** and spawns the chosen MCP server through either stdio or the streamable-HTTP transport. `tools.uninstall` undoes it. |

### Plus one new layer above turns: Missions

A user prompt is a single Turn. A **Mission** is multiple Turns chained
toward one bigger goal. `POST /api/threads/{tid}/missions` with a goal,
HUXForm breaks it into 3-7 concrete steps, spawns one Turn per step, and
auto-advances when the prior step's UI reaches the stage. Each step
renders its **own** mini-app with its own metaphor.

```text
Mission: "compare three small electric SUVs under €50k"

  step 1  ▶  Research SUVs in Europe        → "Small Electric SUV Showroom"  research-pipeline ribbon, dark museum case
  step 2  ▶  Build comparison board         → "ELECTRIC SUV SHOWROOM"       glossy auto-dealer with line-art silhouettes
  step 3  ▶  Deliver final verdict          → "FINAL VERDICT"                F1-style podium with Tesla Model Y at #1
```

Same mission. Three completely different interfaces, picked for what each step actually needs.

---

## Why "non-template"

A normal LLM-generated UI converges on the same generic look: three-column
dark cards, sidebar, hamburger, glassmorphism. Every task ends up feeling the
same. HUXForm fights this in two places:

1. **The Director** outputs a structured *visual brief* — a concrete metaphor
   (a duplicate-finder bench, a sonar sweep, a museum specimen card),
   palette, typography, motion, and an **explicit list of banned defaults**.
2. **The UI Generator** treats the brief as a constraint and refuses to fall
   back to the usual SaaS-app defaults.

The shell itself dissolves while you work: when a task is on stage, the
chrome fades, the palette of the generated app bleeds into the surrounding
frame, and the only thing on screen is the mini-app HUXForm built for *this*
moment.

  
    
      
        
        explainer · meteo station card"what is the current weather in New York City?" — Researcher called web.search, parsed real conditions from AccuWeather + Weather Underground; inline-SVG sun/cloud, real 56°F / 63% humidity baked in
      
      
        
        report · field assessment"find me the 5 best MCP servers for filesystem access" — Researcher called tools.discover + web.search; rendered as a botanist's field notebook with real trust scores and download counts
      
    
    
      
        
        generated_app · vintage scientific chart"draw me a periodic table styled as a vintage poster" — streamed live: parchment appears first, then ornate Victorian header, then the grid fills row-by-row. how streaming works ↓
      
      
        
        evolved · noble-gas dialFrom the periodic-table iframe, agui.evolve("circular dial, only noble gases, keep parchment palette"). Same turn, same state — new shape, same identity. how evolve works ↓
      
    
    
      
        
          
            
              
              mission · step 1/3"Research available small electric SUVs under €50k" — research-pipeline ribbon, dark museum case
            
            
              
              mission · step 2/3"Build comparison board" — glossy auto-dealer with line-art silhouettes, real spec rows, "BEST VALUE" badge
            
            
              
              mission · step 3/3"Deliver final verdict" — F1-style podium ceremony, Tesla Model Y at #1, "RACE STEWARD ANNOUNCEMENT"
            
          
        
        One mission. Three completely different metaphors. The Mission loop chose them, the Director designed them, the Researcher fed them real data, the Generator drew them live.
      
    
  

---

## Quick start

Clone the repo and run one script. It checks your Python and Node versions,
creates a virtualenv, installs dependencies, prompts for an LLM API key
(any Anthropic-compatible or OpenAI-compatible provider), starts both
servers and opens your browser.

**macOS / Linux / WSL**

```bash
git clone https://github.com/agiwhitelist/HUXForm.git
cd HUXForm
./bin/huxform
```

**Windows (PowerShell 7+)**

```powershell
git clone https://github.com/agiwhitelist/HUXForm.git
cd HUXForm
.\bin\huxform.ps1
```

That's it. The script does the rest:

```text
◇ HUXForm  — the interface takes the shape of the task
  ────────────────────────────────────────────────────

  setup
  ✓  python3 / node / npm preflight
  paste your LLM API key  ⟶  ······
  ✓  wrote .env
  api · creating Python venv
  api · installing dependencies
  web · installing dependencies
  ✓  setup complete.

  starting api on :8001 · web on :5173
  ✓  api ready (pid 12345)
  ✓  web ready (pid 67890)

  → http://localhost:5173
```

Next runs just need `./bin/huxform` (or `.\bin\huxform.ps1`) — setup is
skipped automatically.

### What you need before you start

|              | Version | Notes |
|--------------|---------|------|
| Python       | 3.11+   | `python3 --version` |
| Node.js      | 20+     | `node --version` |
| npm          | 10+     | bundled with Node |
| An LLM key   | —       | Any Anthropic-compatible or OpenAI-compatible provider. Bring your own model. |

Anthropic, OpenAI, MiniMax, OpenRouter, Groq, Together, AWS Bedrock,
Ollama — anything that speaks one of the two protocols works. Edit `.env`
after the first run to switch (see [Provider configuration](#provider-configuration)).

### Other ways to run

```bash
make setup     # one-time install
make start     # equivalent to ./bin/huxform start
make doctor    # preflight check
make clean     # remove .venv / node_modules / data

docker compose up --build       # dev (web :5173, api :8001)
docker build --target production -t huxform .   # prod single image (nginx + uvicorn)
```

---

## Architecture

  

| Module                              | Role                                                                                                   |
|-------------------------------------|--------------------------------------------------------------------------------------------------------|
| `apps/api/src/director.py`          | One LLM pass → presentation plan + visual brief (palette, typography, layout, motion, banned defaults) |
| `apps/api/src/researcher.py`        | Server-side ReAct loop. Calls read/network tools before codegen; results land in `turn.state.research`.|
| `apps/api/src/codegen.py`           | UI Generator. Streams HTML token-by-token; consumes the brief + research; supports `agui.evolve()` regeneration.|
| `apps/api/src/mission.py`           | Mission planner + driver. Breaks a goal into 3-7 steps, spawns one Turn per step, auto-advances.       |
| `apps/api/src/runtime_stub.py`      | `window.agui.*` shim injected into every generated document (`agui.research`, `agui.evolve`, …).        |
| `apps/api/src/executor.py`          | Tool Broker + Permission Layer + dry-run + approvals.                                                  |
| `apps/api/src/tools.py`             | Built-in capabilities (LLM, data.\*, web.\*, files.read, task.\*, tools.discover/install/uninstall, optional cli.\*). |
| `apps/api/src/web_search.py`        | Multi-provider web search: Tavily → Brave → Serper → DuckDuckGo (default, no key) → SearXNG.           |
| `apps/api/src/discovery.py`         | Tool Discovery + Capability Registry. `discover_tools()` ranks MCP candidates and audits READMEs.      |
| `apps/api/src/mcp_client.py`        | MCP client. **stdio** subprocesses and **streamable-HTTP** remotes — both registered as `mcp..`.|
| `apps/api/src/openapi_adapter.py`   | Loads any OpenAPI 3.x spec, exposes every operation as `openapi..`.                         |
| `apps/api/src/llm.py`               | Provider-agnostic LLM client. Anthropic Messages + OpenAI Chat Completions, blocking + streaming.      |
| `apps/api/src/narrator.py`          | Turns raw events into single-sentence human commentary.                                                |
| `apps/api/src/tasks.py`             | Domain model: Thread → Turn → events / state / files; Mission → Steps.                                 |
| `apps/api/src/persistence.py`       | SQLite store with hydration on boot.                                                                   |
| `apps/api/src/audit.py`             | Append-only audit of tool calls and approvals.                                                         |
| `apps/web/src/App.tsx · Turn.tsx`   | Stage-first shell, palette sync, auto-fading chrome, history overlay, streaming-iframe srcDoc preview, high-risk approval modal.|
| `apps/web/src/bridge.ts`            | Per-turn iframe ↔ backend bridge. Tool calls, file upload, SSE events, `agui.evolve` proxy.            |

---

## The interaction model

- **Stage first.** Each user prompt opens a *session*. The session is a
  full-bleed stage — no chat scrollback, no plan card in the way. The
  generated mini-app fills the screen; the shell fades away.
- **Plan steering.** Before codegen burns tokens you can ask the agent to
  confirm its approach (auto-proceed is on by default for safe tasks; it's
  off for destructive ones).
- **Refine + regenerate.** "Refine" the running interface with a sentence —
  "warmer palette, denser table, add an export button" — and HUXForm
  regenerates the document while keeping the metaphor.
- **File attachments.** Drop files into the generated UI (it has a real
  picker bound to the bridge), or attach them in the prompt before pressing
  enter. Available inside the iframe via `await agui.readFile(id)`.
- **Cancel anytime.** Hard cancel releases pending approvals, stops the
  pipeline and persists the cancelled state.
- **Inspector.** Per-turn raw event stream + token usage, hidden behind a
  side drawer (toggle with `⌘.`).
- **Sessions overlay.** Press `\` to open the gallery of past sessions —
  each card carries the palette swatches of its concept.

---

## Streaming codegen — watch the app being drawn

The Codegen pass uses `LLMClient.complete_stream()` (Anthropic SSE or OpenAI
SSE — both supported) and pushes the accumulated buffer through an
`on_chunk` callback every ~120 ms / ~400 chars. The driver emits each
buffer as `codegen_chunk` on the turn's SSE stream. The host shell pipes
those into `iframe.srcDoc` after a small sanitisation pass (strips inline
`` blocks, trailing partial tags, and any leading markdown fence
the model might wrap the document in).

What the user sees:

```text
[t = 0.0 s]  curtain · "phase 02 · drawing"
[t = 1.2 s]  parchment background appears in the iframe
[t = 1.8 s]  ornate Victorian title materializes
[t = 3.0 s]  table grid starts filling, row by row
[t = 7.0 s]  inline SVG elements (sun, cloud, sigils) draw in
[t = 9.0 s]  ui_ready → iframe swaps to live bridge-wired URL
```

On `ui_ready` the iframe `srcDoc` is cleared and `src` is set to
`/api/turns/{id}/ui` — the live URL serves the same HTML with the runtime
stub injected, so the bridge wakes up and the generated JS starts running.

This works even when the LLM hits 6-7 seconds of latency: the user is
*reading* a real interface forming on the page, not staring at a spinner.

---

## Self-evolving UI (`agui.evolve`)

From inside a generated mini-app the JavaScript can ask HUXForm to
**redraw the whole document around the same task state**:

```js
// inside the generated UI, on a button click
document.getElementById('compare').addEventListener('click', async () => {
  await agui.evolve('switch to a side-by-side table comparing both options, keep palette');
});
```

Under the hood the bridge posts to `POST /api/turns/{turn_id}/regenerate`
with the refine note, the codegen runs again (also streamed), and the
iframe swaps to the new HTML on `ui_ready`. The turn ID, thread, state,
files, and research results are all preserved — only the document changes.

The codegen prompt forbids the generated UI from using `display:none`
toggles to hide alternate views: when the user wants a different shape,
call `agui.evolve()`. The interface stays alive instead of accumulating
dead UI surface.

Real example: starting from a full periodic-table mini-app, calling
`agui.evolve('circular dial, only noble gases, keep parchment palette')`
produces a new document where the layout is a circular dial with He / Ne /
Ar / Kr cards arranged around it, palette preserved, title rewritten —
**same turn**.

---

## Mission loop — multi-turn agentic execution

A Turn is one user prompt → one mini-app. A Mission is one **goal** → 3-7
auto-spawned Turns, each producing its own mini-app, advancing the goal
step by step.

```bash
curl -X POST http://localhost:8001/api/threads/{thread_id}/missions \
  -H 'content-type: application/json' \
  -d '{"goal": "compare three small electric SUVs under 50k EUR"}'
# → { "mission_id": "...", "thread_id": "..." }
```

What happens:

1. `apps/api/sr

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [agiwhitelist](https://github.com/agiwhitelist)
- **Source:** [agiwhitelist/HUXForm](https://github.com/agiwhitelist/HUXForm)
- **License:** MIT
- **Homepage:** https://agiwhitelist.github.io/HUXForm/

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-agiwhitelist-huxform
- Seller: https://agentstack.voostack.com/s/agiwhitelist
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
