MCP DevTools. Structured errors. Runtime guardrails. Your AI writes better code with What Framework.
import { mount, signal, computed } from 'what-framework' function Counter() { const count = signal(0) const doubled = computed(() => count() * 2) return ( <div> <button onClick={() => count(c => c + 1)}> Count: {count()} </button> <p>Doubled: {doubled()}</p> </div> ) } mount(<Counter />, '#app')
AI agents generate more frontend code every month. But existing frameworks give them nothing to work with.
Stack traces full of minified internals. "Cannot read property of undefined" with no hint where the signal, effect, or component went wrong. Agents guess, retry, break more things.
When an agent builds a component, it cannot see signal values, dependency graphs, or effect states at runtime. Debugging is blind.
Forgot to clean up an effect? Created an infinite reactive loop? Passed wrong props? Other frameworks stay quiet. The bug ships.
Autocomplete, hover docs, and inline hints help humans in IDEs. AI agents need structured, machine-readable contracts they can query programmatically.
Every layer of What Framework gives AI agents the context they need to write correct code, catch errors, and ship faster.
AI agents inspect every signal, effect, and component in a running app via the Model Context Protocol. Live state, dependency graphs, performance data -- all queryable.
// Agent calls MCP tool: what_signals({ filter: "count" }) // Returns: { "summary": "6 signals total. 1 match filter 'count'. Values: count=5", "count": 1, "signals": [{ "id": 3, "name": "count", "value": 5, "componentId": 2 }] }
A catalogue of ten ERR_ codes, each with a human message, a suggestion, and a code example an agent can query offline. Every error object serializes to JSON, so agents parse, understand, and fix it in a single pass.
{ "code": "ERR_SIGNAL_WRITE_IN_RENDER",
"message": "Signal \"count\" written during render
of component \"Counter\". This triggers re-execution.",
"suggestion": "Move signal writes into event handlers,
effects, or onMount(). The component body should only
read signals, not write them.",
"component": "Counter", "signal": "count" }
In dev mode the runtime catches infinite effect loops and refuses raw-string innerHTML outright. With what-devtools installed (the scaffold adds it), it also warns on signal misuse. Lint rules catch the rest before they hit production.
// Runtime catches this automatically: effect(() => { count(count() + 1) // Infinite loop }) // [what] Possible infinite effect loop detected // (25 iterations). Likely cause: an effect writes to // a signal it also reads, creating a cycle. Use // untrack() to read signals without subscribing.
Write normal JSX. The compiler transforms it into fine-grained reactive DOM operations. No virtual DOM diff. Components run once. Agents write familiar code, the compiler optimizes it.
// You write: <p>{count()}</p> // Compiler outputs: direct DOM text node update // No re-renders. No VDOM. No reconciliation. // Buildless (no compiler)? No JSX either, so write it with h(): h('p', {}, () => count())
A small reactive core (signal, computed, effect, batch) plus opt-in modules. ~8KB typical-app runtime, zero third-party code in the shipped bundle, tree-shakeable. Agents generate less code, ship smaller bundles, and reason about a smaller API surface.
// The full API an agent needs to learn: import { signal, computed, effect, mount, Show, For, createStore } from 'what-framework' // ~8KB gzipped. That's it.
The left panel is what you write. The right is what an AI agent can query via MCP DevTools at runtime.
import { signal, computed, mount, For } from 'what-framework' function TodoApp() { const todos = signal([], 'todos') const filter = signal('all', 'filter') const visible = computed(() => { if (filter() === 'all') return todos() const done = filter() === 'done' return todos().filter(t => t.done === done) }) const remaining = computed(() => todos().filter(t => !t.done).length ) return ( <main> <h1>Todos ({remaining()})</h1> <ul> <For each={visible}> {todo => <li>{todo.text}</li>} </For> </ul> </main> ) }
// what_explain({ componentId: 1 }) on TodoApp (abridged) { "summary": "TodoApp: 2 signals (todos=[{\"text\":\"Ship v1\"..., filter=\"all\"), 4 effects (effect_1 (ran 1x), ...)", "component": { "id": 1, "name": "TodoApp", "parentId": null }, "signals": [ { "id": 3, "name": "todos", "componentId": 1, "value": [ { "text": "Ship v1", "done": false }, { "text": "Write tests", "done": true } ] }, { "id": 4, "name": "filter", "value": "all", "componentId": 1 } ], "effects": [ { "id": 1, "name": "effect_1", "runCount": 1, "depSignalIds": [4, 3], "depSignalNames": ["filter", "todos"] }, { "id": 2, "name": "effect_2", "runCount": 1, "depSignalIds": [3], "depSignalNames": ["todos"] }, { "id": 3, "name": "effect_3", "runCount": 0, "depSignalIds": [] }, { "id": 4, "name": "effect_4", "runCount": 0, "depSignalIds": [] } ], "errors": [], "counts": { "signals": 2, "effects": 4, "errors": 0 } }
Connect your AI agent to a running What app. Works with Claude Code, Cursor, and any MCP-compatible client. create-what writes both files below for you and installs the browser bridge. On an existing project add it yourself: npm i -D what-devtools what-devtools-mcp, then put whatDevTools() from what-devtools-mcp/vite-plugin in your Vite plugins. Without that bridge only the five offline tools answer (what_connection_status, what_lint, what_validate, what_scaffold, what_fix); the other 24 need a live page.
Add the What DevTools MCP server to your project's Claude Code config.
// .mcp.json (project root) { "mcpServers": { "what-devtools-mcp": { "command": "npx", "args": ["what-devtools-mcp"] } } }
Add the MCP server to your Cursor workspace settings.
// .cursor/mcp.json { "mcpServers": { "what-devtools-mcp": { "command": "npx", "args": ["what-devtools-mcp"] } } }
A factual look at AI-agent capabilities across frameworks.
| What | React | Solid | Svelte | |
|---|---|---|---|---|
| MCP DevTools | Built in | No | No | No |
| Structured Errors | JSON + suggestion | Stack trace | Stack trace | Warnings |
| Runtime Guardrails | Loops, XSS, signal misuse | StrictMode | Minimal | Minimal |
| Reactivity | Fine-grained signals | VDOM diff | Fine-grained signals | Compiler runes |
| JSX | Yes | Yes | Yes | Custom syntax |
| SSR / Islands | Built in | Via Next.js | SolidStart | SvelteKit |
| React Library Compat | Via what-react | Native | No | No |
| Runtime Size* | ~8KB | ~61KB | ~3.5KB | ~11KB |
* Gzipped JS from a Vite production build of the same minimal counter app, measured 2026-08-11: What 0.13.4 7.97KB, React 19.2 + react-dom 60.7KB, Solid 1.9 3.6KB, Svelte 5.56 11.7KB. Real-world app bundles vary by features used and differ between frameworks at app scale, so these figures don't imply byte-for-byte parity. Solid ships the smallest runtime here; What is not the smallest.
Every package works standalone. Grab what you need.
Signals, computed, effects, components, forms, routing. The full reactive runtime.
MCP server for AI agents. Inspect signals, components, effects, and performance in real time. Pairs with what-devtools, the in-browser inspector that bridges it to the live page.
JSX transform, optimizing compiler, fine-grained reactivity output.
Client-side routing with dynamic params, nested layouts, and View Transitions.
React compatibility layer. Run React ecosystem libraries with little or no code change.
Project scaffolder. One command to start building.
MCP DevTools. Structured errors. Runtime guardrails. One command to start.