wiri
by ehm-93
README.md
# Wiri
Wiri is a headless wireframing MCP server designed for an LLM operator. It stores each screen as a small semantic scene graph, lays elements out without absolute coordinates, and closes the editing loop with deterministic renders and lint findings.
The v1 contract is in [SPEC.md](SPEC.md). The persisted document shape is also available as [schemas/wire-document.schema.json](schemas/wire-document.schema.json).
## Requirements
- Node.js 20.9 or newer
- A local directory for documents and exports
Wiri runs entirely on the local machine. It makes no network requests and sends no telemetry. Documents, checkpoint history, rendered exports, form values, and annotations are stored as plaintext; do not use production secrets as wireframe content.
## Install and run
```sh
npm install
npm run build
node dist/index.js --workspace ./wireframes
```
The process speaks MCP over standard input/output. It writes protocol messages only to stdout and exits when its client disconnects. `WIRI_WORKSPACE` can set the workspace when `--workspace` is omitted; the current directory is the final default.
An MCP client configuration can launch the built server like this (use absolute paths in a real configuration):
```json
{
"mcpServers": {
"wiri": {
"command": "node",
"args": [
"/absolute/path/to/wiri/dist/index.js",
"--workspace",
"/absolute/path/to/wireframes"
]
}
}
}
```
For development, `npm run dev -- --workspace ./wireframes` runs the TypeScript entry point directly.
## Canonical workflow
1. Call `create_document`, then add one or more screens with `create_screen`.
2. Call `get_tree` before editing a screen that has not been read in the current context.
3. Prefer one or two atomic `batch` calls to build a screen. A later operation can refer to a node created by an earlier add with `$0`, `$1`, and so on.
4. Use `render` for visual feedback and `lint` for deterministic findings.
5. Use `checkpoint` before a larger revision; `diff`, `undo`, and `redo` make changes inspectable and reversible.
6. Use `links` or `render_flow` to verify navigation, then `export` to produce PNG, SVG, or static HTML.
A compact signup flow can be built in one document with this shape:
```text
welcome --start_btn--> email --continue_btn--> password
password --continue_btn--> verify --verify_btn--> done
```
Each arrow is simply a `to` prop on its source button. HTML export turns those links into fragment navigation between screen sections.
Layered application surfaces use constrained anchors rather than freeform coordinates. For example, a full-screen image or map placeholder can use `anchor="stretch"`, while any number of `variant="fab"` buttons live in stacks anchored to screen corners. Semantic left, right, and bottom drawers are direct children of the same layer.
## Storage
The server owns one active document at a time and writes successful mutations before returning:
```text
<workspace>/
checkout_redesign.wire.json
checkout_redesign.history.json
exports/
...
```
Writes use a temporary file plus atomic rename. Opening another document clears session-only undo/redo stacks; named checkpoints persist in the history file. Export files are safe to regenerate and overwrite deterministically.
## Commands
```sh
npm test # unit and integration tests
npm run typecheck # strict TypeScript check
npm run build # emit dist/
npm start -- --workspace ./wireframes
```
The server intentionally exposes tools only in v1—no MCP resources or prompts. Run `node dist/index.js --help` for command-line options.
## Limits and troubleshooting
- Names and ids must match `[a-z][a-z0-9_]{0,31}`.
- A document supports 50 screens; a screen supports 300 nodes; a batch supports 100 operations.
- Rendered height is capped at 4000 px.
- If a call returns `NO_ACTIVE_DOCUMENT`, call `create_document` or `open_document` first.
- If a parent is rejected, call `get_tree` and choose `root`, `overlay`, or an existing container id.
- A failed call and a failed batch never change the active graph or its document file.
Wiri reads schema version 1 only. Malformed files, unknown node types, invalid props, or unsupported schema versions are rejected rather than repaired silently.
## License notices
Rendered output embeds Inter from `@fontsource/inter`, distributed under the SIL Open Font License 1.1. See [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues