web-gui-mcp is a Python MCP server that allows your agent to outsource the html generation and rendering. It stores artifacts in memory and can
return either full HTML or an MCP App-style ui:// resource URI. Inspired by https://thariqs.github.io/html-effectiveness/ but with cost in mind.
Agent/LLM entrypoints:
README.agent.md: setup, Claude Code, Cursor, and agent usage guidance.llms.txt: concise machine-readable orientation.
The renderer supports the original safe static v0.1 contract and an additive
Chrome-first v0.2 contract with richer Studio Sheet layouts, sandboxed prototypes,
and deterministic local interactions.
uv sync
uv run pytest
uv run pytest tests/test_chromium_smoke.py
uv run python scripts/render_example.py examples/implementation_plan.json /tmp/web-gui-plan.htmlWithout uv:
python -m venv .venv
. .venv/bin/activate
pip install -e ".[dev]"
pytest
pytest tests/test_chromium_smoke.py
python scripts/render_example.py examples/implementation_plan.json /tmp/web-gui-plan.htmlThe Chromium smoke tests target local Google Chrome/Chromium through Playwright.
uv run web-gui-mcpThe server exposes:
search_artifact_patternsget_artifact_schemarender_artifactpatch_artifactlint_artifactexport_artifactlist_artifacts
It also serves:
ui://web-gui/runtime/v0.1.cssui://web-gui/runtime/v0.1.jsui://web-gui/artifacts/{artifact_id}
v0.1 patterns remain supported:
implementation_plancode_review_explainerdesign_variant_gridresearch_reportcustom_editor
v0.2 adds Chrome-first artifact families:
approach_comparisonvisual_direction_boardimplementation_handoffpr_review_workspacepr_author_writeupmodule_mapdesign_system_referencecomponent_variant_matrixanimation_tunerclickable_flowdiagram_sheetannotated_flowchartslide_deckfeature_explainerconcept_explainerstatus_reportincident_reporttriage_boardfeature_flag_editorprompt_tuner
Use v = "0.2" when an artifact needs richer local behavior:
- tabs, filters, collapsibles, copy/export buttons
- sliders and replay controls
- keyboard slide navigation
- clickable diagram inspectors
- drag/reorder boards
- dependency-aware toggles
- live prompt-template previews
Prototype and editor surfaces use sandboxed iframe srcdoc documents with
sandbox="allow-scripts". The sandbox does not allow same-origin access or network
requests. Model output remains declarative and escaped; only the known renderer
runtime executes.
Add a local MCP server entry to your Codex config, using this repository as cwd:
[mcp_servers.web_gui_mcp]
command = "uv"
args = ["run", "web-gui-mcp"]
cwd = "/Users/hzuo/src/web-gui-mcp"
startup_timeout_sec = 20
tool_timeout_sec = 60
enabled = trueWithout uv:
[mcp_servers.web_gui_mcp]
command = "python"
args = ["-m", "web_gui_mcp.server"]
cwd = "/Users/hzuo/src/web-gui-mcp"
startup_timeout_sec = 20
tool_timeout_sec = 60
enabled = trueFor Claude Code and Cursor configuration snippets, see README.agent.md.
render_artifact accepts a compact semantic spec:
{
"spec": {
"v": "0.2",
"artifact": "feature_explainer",
"title": "Rate Limiting Explainer",
"sections": [
{
"kind": "tabs",
"title": "How it works",
"tabs": [
{ "id": "tldr", "label": "TL;DR", "body": "Requests are keyed by account and route." },
{ "id": "path", "label": "Path", "body": "Middleware increments usage and emits headers." }
]
}
]
},
"delivery": "static_html"
}Use delivery = "mcp_app" or delivery = "resource_only" when you want a stored
ui://web-gui/artifacts/{artifact_id} URI instead of returning full HTML through the
tool response.
- All model-provided text is HTML-escaped.
html_previewis escaped text by default.- v0.2 prototype/editor sections use sandboxed iframe
srcdocdocuments. - Generated interactions use deterministic runtime code; model-generated JavaScript is not allowed.
- JSON state embedded in
<script type="application/json">escapes<,>,&, U+2028, and U+2029 to prevent</script>breakout. - The renderer does not execute or copy arbitrary model-generated JavaScript.
- CSS, HTML structure, and optional local runtime behavior are deterministic.