The culminating research project: a spec-driven web component platform where a single YAML specification is the source of truth. Write YAML once, get a live interactive preview, then export to production frameworks.
| Server | Port | Role | Repo | Visibility |
|---|---|---|---|---|
| Juris | 3005 | Central runtime — parses YAML, manages state, generates previews and exports | juris-mcp-server | private |
| SVG Icons | 3002 | 18,368 icons across 6 families, unified family::name:variant syntax |
svg-mcp-server | private |
| Tailwind | 3001 | Real-time CSS generation from component markup | tailwind-mcp-server | private |
| Lit | 3004 | Exports YAML specs to production Lit web components | lit-mcp-server | private |
| Stencil | 3003 | Exports YAML specs to framework-agnostic Stencil web components | stencil-mcp-server | private |
All repos under https://github.com/eswat2. The full Docker-orchestrated prototype lives in proto-spec-dkr [private].
A YAML spec defines state, elements, and actions:
state:
clickCount: { type: number, defaultValue: 0 }
elements:
- type: md:button
icon: "material::add:outline"
text: "Clicked {{clickCount}} times"
onClick: incrementCounter
actions:
incrementCounter:
type: setState
target: clickCount
value: "{{clickCount + 1}}"
Juris parses this into a reactive runtime. State interpolation ({{expr}}), event handling, and UI updates are all automatic — no manual DOM manipulation.
Every server exposes both MCP (for LLMs/agents) and REST (for browsers, CLI tools, editor plugins). Same service, same logic, two protocols. A Sublime Text plugin triggers live Proofs previews from the editor with a hotkey — hit the hotkey, the browser opens and auto-refreshes via SSE.
The platform has two viewing modes for any YAML spec:
The runtime layer that brings a YAML spec to life:
{{state}} interpolation, event handling, and UI updatesemitEvent actions in the YAML fire through the bus and can be caught by any componentfamily::name:variant, instant clean SVG from the 18k+ icon library. Used only for the dynamic case where icon identity isn't known until user interaction (e.g. the selected icon display in icon-gallery). For static icons, svg-mcp-server resolves every family::name:variant reference at transform time — juris-mcp-server, lit-mcp-server, and stencil-mcp-server all inline the actual SVG markup into their output before the renderer ever sees it. The runtime has no icon dependency unless state demands it.showToast actionsThe platform is built with AI but designed to be fully deterministic at runtime. The probabilistic part (LLM generating or editing YAML) stays in the authoring phase. Once the YAML is fed in, the runtime is a collection of services talking to each other — no LLM in the loop, no probabilistic behavior, predictable and observable execution every time.
The 5-server topology is a development topology, not a production one. What gets deployed is the self-contained output from the export servers — SVG already inlined, no server dependencies at runtime. An app with only static icons needs nothing running to function. The svg-mcp-server becomes an optional runtime enhancement only when proto-svg-icon is in play for dynamic icon selection.
The platform deliberately converged on one renderer (Juris), one spec format (YAML), and two interfaces (MCP + REST). Three renderers were removed in Issue #99 — a 70% reduction in infrastructure code, 40% faster component initialization, and zero feature loss. Removing choices made the architecture more extensible.
The export contract is intentionally minimal: receive a YAML spec, return a compiled deployable dist. Any framework can become an export target by building a new MCP server that honors that contract. Lit and Stencil are not just two options — they're proof that the pattern is valid. Every subsequent export server (Vue, React, Svelte, whatever emerges next) just executes the same playbook against its own framework toolchain. The core platform — Juris, SVG server, Tailwind server — never changes.
The platform evolved through several Docker-based prototypes before reaching the current form (all private):
An earlier iteration used a browser-based mini-IDE — split-pane YAML editor on the left, live preview and devtools on the right, with an Export dropdown targeting Stencil and Lit. It was fully functional but was superseded by the Sublime Text plugin approach: rather than building a browser editor that could never match a dedicated editor, the plugin lets Sublime own the authoring surface and the browser own the preview. The SSE pipe between them — plugin reads the buffer, pushes YAML to juris-mcp-server, browser auto-refreshes — replaced an entire browser editor pane with roughly 50 lines of plugin code.
By 2026, three high-profile efforts converged on essentially the same pattern: MCP Apps extensions, Google's A2UI declarative protocol, and Vercel's json-render (which added YAML support in March 2026 — React only). All solving the same problem — give agents a constrained, safe way to describe UIs instead of raw DOM. This platform had the full runtime observability, templating engine, dual-protocol access, and deterministic execution in place in 2025, a year earlier.