Lolly Beta
Launch App

Driving Lolly from an AI agent

Give your model a deterministic, reviewable creative layer instead of asking it to hallucinate pixels. A tool invocation is just a URL with parameters - a few tokens that produce a press-quality file, the same way every time. No image model, no creative drift - and driven locally (URL or CLI), no data leaving the device. The hosted MCP endpoint is the one server-side path, covered below and inventoried on Server Surface.

Machine-readable entry points

Start here rather than scraping pages. Each file is generated by the docs build from the same sources the human pages come from, and each is served at the site root as well as under /info/.

FileWhat it is for
/agents.mdThe short version of this page for a machine reader: entry points, the URL grammar, how to get bytes and the rules that save a round trip.
/llms.txtThe docs index in the llms.txt convention - one line per page, linking its markdown twin.
/llms-full.txtEvery docs page in one file, in the index's order, for a reader that wants the whole corpus in one fetch.
/.well-known/lolly.jsonThe discovery record: where the catalog, the manifests, the render route, the MCP endpoints and the files above live on this deployment.
/openapi.jsonThe HTTP surface in OpenAPI 3.1 - the hot-link render route with its refusals, the catalog and manifest reads and the MCP endpoint's transport.
/info/capabilities.jsonFormat claims: what Lolly reads and writes per format and what each format's own metadata carries.
/catalog/tools/index.jsonThe generated tool index; /tools/<id>/tool.json is one tool's manifest with every input, default and format.
/info/skills/lolly/SKILL.mdThe agent skill: one page an agent loads to drive Lolly across every surface, with references for URL mode, the surfaces, the whole catalogue, the three document tools (chart, design, deck) and renovating an old deck into the design system (Rebrand).

The same set exists on every deployment, so an agent pointed at a self-hosted instance discovers that instance's own endpoints from its own well-known record.

Fast path for a model

When a model points at one Lolly instance, use the smallest path that answers the task:

  1. Read the instance discovery record and request only the relevant tool or format.
  2. Describe the chosen tool or template and build a stack plan from its declared inputs.
  3. Validate and render in one workflow when the instance supports that combined call.
  4. Return the artifact, editable recipe, checks and one next action.

For a known recipe, do not enumerate the whole catalog or repeat validation as a separate call. For a revision, send stable layer patches or changed inputs instead of the whole document. A result is complete when its declared checks pass. Ask for human review only when the task states a requirement this instance cannot measure, such as physical print appearance or subjective approval. Otherwise report the result and continue.

Keep these outcomes distinct: complete, partial, approximate, blocked, failed and unknown. Say what changed, what was preserved, what was checked and what remains unknown. Never describe an unchecked property as passed.

The model: a URL is the API

Every tool is fully described by its URL. The agent's job is to build that URL (or the equivalent CLI command) from structured inputs:

https://<host>/#/tool/<tool-id>?<input>=<value>&<input>=<value>

Open it and the tool renders with those inputs applied. Add reserved params to control output and trigger a download. For a pinned tool, profile, asset set and supported format, the same inputs reproduce the same recipe result; formats with timestamps, browser encoding or external resources have narrower guarantees described by the format documentation.

What /#/tool/qr-code?url=https://suse.com renders - the bare canvas, no chrome, straight from the parameters in the linksigned by Lollyvector SVGCheck it yourselfGet the signed file1 path~1.4k nodes12 KBTry it in the app

Use Lolly to generate a QR code:
  tool: qr-code
  url: "https://example.com"
  format: svg
Return the editable file URL and the exact inputs used.

Discover a tool's inputs

Don't guess parameters - read them. The tool's manifest (tools/<id>/tool.json) lists every input id, type and default, or use the CLI:

pnpm run cli qr-code  # prints inputs, defaults, and supported formats
pnpm run cli                      # lists every available tool

Feed that schema to the model so it only emits valid inputs.

Reserved parameters

These are the common ones; anything outside the full reserved set is a tool input. (Full reference: URL Mode.)

ParamEffect
formatOutput format (png, svg, pdf, mp4, …)
exportPresence flag - render and download immediately on load
copyPresence flag - copy the result to the clipboard on load
width / w, height / hOutput size (value in unit)
unit, dpiPhysical sizing (mm/cm/in/pt) + raster resolution
bleed, marksPrint bleed and crop marks
profileColour profile - raster ICC (srgb/none) or CMYK press condition
filename, outputDownload filename / CLI output path
passwordLock the exported PDF
_vPin the tool version for stable output
slotOpen a saved session

The complete reserved set also includes full, options, c2pa, imprint, durable, meta, hdr, depth, cuts, lang, designv, template, nostage, z and zx; everything else is forwarded to the tool as an input. (The engine's RESERVED set in engine/src/url-mode.ts is the source of truth - see URL Mode.)

So a one-shot, ready-to-download link is just:

/#/tool/qr-code?url=https://suse.com&format=svg&export

Getting an actual file

(The lean node CLI renders SVG and text/data formats; raster/PDF/video need the desktop-bundled build - see CLI.)

Pipe stdout straight into another step in your pipeline.

A few tools won't hand back a file this way:

The MCP server (native endpoint)

Beyond building URLs by hand, Lolly ships an optional Model Context Protocol server - a native endpoint any MCP client (an agent runtime, an IDE, a CLI, a hosted assistant) connects to directly. It exposes the catalogue and the render path as callable tools, so an agent can discover a tool, fill its declared inputs and get back a finished file plus an editable lolly.tools link - with no app update, because tools sync to the server as data.

Core workflow verbs:

ToolDoes
lolly_list_toolsList / search the catalogue (by text, status, category, format or capability); use limit to keep discovery small.
lolly_describe_toolOne tool's full input JSON Schema, built-in templates/presets, supported formats, canvas size and examples.
lolly_validateValidate inputs and return path-specific errors before a compile, URL build or render. Design also returns its artboard/layer tree and structural findings.
lolly_compile / lolly_inspect / lolly_measureCompile once, inspect the semantic document and measure it without rasterising.
lolly_measure_textWhere a Design text box's lines break and how tall it is, before it is drawn, with the faces the canvas loads. The same measure as lolly measure --text.
lolly_packageA Design document as a .lolly the app reopens as the same document, with the pictures you supply and its name. The same writer as lolly package.
lolly_composeSlides laid out from the design system's slide master: name an archetype per slide and fill its slots, and get a Design document with the master's margins, type, furniture and bindings, so its PowerPoint export has real slide layouts and placeholders. mode: "list" gives the archetypes, mode: "suggest" drafts a spec from a deck. The same composer as lolly compose. A hosted server receives a deck passed as source.
lolly_build_urlBuild a shareable, editable link + raw render URL - without rendering.
lolly_renderRender a tool to a file (returns the bytes plus the editable link).
lolly_transformRun an on-device file utility (strip-data, compress-pdf) on a file you supply.
lolly_redactRedact regions of an image, SVG or PDF on-device - covered content is destroyed and the file rebuilt, so nothing is recoverable underneath.
lolly_verifyVerify a file's Content Credentials (C2PA) - the verdict, signer identity, edit history and embedded metadata. Checked in-process, never stored.
lolly_rebrandRenovate an old .pptx deck into the active design system, in stages (capabilities, plan, compile, inspect) - see reference/rebrand.md. Processed in memory, never stored; capabilities states where a deck you send would go before you send one.
lolly_readRead what a deck says (.pptx, PDF or .psd), slide by slide: text in reading order with roles, speaker notes with their paragraphs, pictures by hash with placement, tables and charts. The same reader as lolly read. Processed in memory, never stored.
lolly_checkCheck a Design document, a .lolly or an export in one findings list: structure, render, brand and house rules, Verify, and fidelity to the source deck. Each finding has a stable code, the layer id and the message the app shows; exitCode matches lolly check. Read the lolly://design-context resource first for the design brief.
lolly_lookLook at a render with a labelled grid in document units (for Design, a layer's own x, y, w, h), or one region of it enlarged. Never an export.
lolly_sample_colorRead the colours at points and name the nearest design-system colour with its distance.
lolly_trace_edgesA render's or image's edges as polylines, optionally as ready Design path layers.

For Design, prefer templateId plus an optional presetId and a small set of input overrides. lolly_describe_tool lists those starting points; the same arguments work with validate, compile, inspect, measure, URL building and render. Inspect the template once to discover its stable layer IDs, then send layerPatches: [{ "id": "s1title", "set": { "text": "Your title" } }] to replace content without resending layer geometry. This lets an agent start from, for example, a slide deck or square poster without inventing raw coordinates.

Use layerOperations to change the layer set itself. It supports strict stable-ID add, duplicate, remove, reparent and reorder operations. Reorder anchors must be siblings. Reparent preserves the layer's geometry and accepts a destination artboardId (null means the pasteboard), plus an optional destination sibling anchor. Every duplicate takes an explicit newId; duplicating a non-empty artboard also requires a complete childIds map. Removing a non-empty artboard requires cascade: true. Operations run before layerPatches, so a newly created or moved layer can be patched in the same call:

{
  "toolId": "design",
  "templateId": "slide-deck",
  "layerOperations": [
    {
      "op": "add",
      "layer": { "id": "s1-kicker", "kind": "text", "frame": "slide1", "text": "Draft" },
      "afterId": "s1title"
    }
  ],
  "layerPatches": [
    { "id": "s1-kicker", "set": { "text": "Agent-added context" } }
  ]
}

Design layers may also carry authoring keys, which start with $ and are lowered to ordinary layers before anything else runs: $in gives a position relative to an artboard, $style sets text by a named style from the design brief, $points and $d draw a path in px, and $stack, $grid and $table lay out repeated rows. The stored document stays in global canvas coordinates with every field written out. The agent skill's Design reference describes every key.

Any format, transparently

lolly_render returns whatever format the tool declares - the server picks how to produce it, and the agent never has to know which engine ran:

Formats are per-tool - you can only request one a tool declares (lolly_describe_tool lists them). Ask a QR tool for svg and you get vector; ask an animated-ad tool for mp4 and you get video - the call is identical either way.

Connect a client

The open endpoint, no token. Anyone can connect to https://lolly.tools/api/mcp: vector and data output, plus png for SVG-native tools, with no sign-in. Calls are limited per address and by a daily budget for the whole endpoint. In Claude Code:

claude mcp add --transport http lolly https://lolly.tools/api/mcp

Any other client takes a config entry like:

{
  "mcpServers": {
    "lolly": { "type": "http", "url": "https://lolly.tools/api/mcp" }
  }
}

The full endpoint, with a token. https://mcp.lolly.tools/mcp renders every format, and authenticates against a shared access token that your Lolly operator holds (the token is never printed in a link or a log). Connect it one of two ways. Full reference, including the open endpoint's limits: the MCP Server page.

A custom connector (OAuth). The full endpoint is also a stateless OAuth 2.1 authorization server, so it drops straight into any MCP client that supports custom connectors:

  1. In your client's connector settings, add a custom connector pointing at https://mcp.lolly.tools/mcp. (Hosted assistants usually expose this under a Connectors or Integrations panel; on team/enterprise plans an admin typically adds it once for everyone.)
  2. Leave the OAuth Client ID / Secret blank - the server registers your client automatically (dynamic client registration).
  3. The client auto-discovers the OAuth server and opens a consent page. Paste the access token and approve - done.

Nothing is stored server-side: the client registration, the authorization code and the tokens are all short-lived signed values verified with a shared secret on each call (PKCE-protected, so a leaked link can't be replayed).

A bearer token (CLI / any HTTP client). The full endpoint also accepts the raw token directly, so scripted clients skip the OAuth dance. Most MCP clients take a config entry like:

{
  "mcpServers": {
    "lolly": {
      "type": "http",
      "url": "https://mcp.lolly.tools/mcp",
      "headers": { "Authorization": "Bearer <your-access-token>" }
    }
  }
}

(Or run it locally over stdio during development - no token needed.)

A hosted add-on - not offline or edge

The MCP server is the one part of Lolly that is a server-side add-on, not an on-device component. Producing the full format range - animations, print PDF, HTML-layout raster - means driving a headless browser against a built web shell, so the full endpoint runs as a hosted service and is not suitable for offline or edge deployments. That full endpoint is live at https://mcp.lolly.tools/mcp; the lightweight serverless endpoint at lolly.tools/api/mcp runs the browser-free tier only (vector, data and PNG for SVG-native tools). The on-device shells - web PWA, desktop, mobile and CLI - remain the offline / air-gapped path. See the MCP Server page for the full reference.

Why this beats prompting an image model

Tips