Install
$ agentstack add mcp-agiwhitelist-huxform ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →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.
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.
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:
- 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.
- 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
git clone https://github.com/agiwhitelist/HUXForm.git
cd HUXForm
./bin/huxform
Windows (PowerShell 7+)
git clone https://github.com/agiwhitelist/HUXForm.git
cd HUXForm
.\bin\huxform.ps1
That's it. The script does the rest:
◇ 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
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:
[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:
// 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.
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:
- `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
- Source: agiwhitelist/HUXForm
- License: MIT
- Homepage: https://agiwhitelist.github.io/HUXForm/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.