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/.
| File | What it is for |
|---|---|
/agents.md | The 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.txt | The docs index in the llms.txt convention - one line per page, linking its markdown twin. |
/llms-full.txt | Every docs page in one file, in the index's order, for a reader that wants the whole corpus in one fetch. |
/.well-known/lolly.json | The discovery record: where the catalog, the manifests, the render route, the MCP endpoints and the files above live on this deployment. |
/openapi.json | The 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.json | Format claims: what Lolly reads and writes per format and what each format's own metadata carries. |
/catalog/tools/index.json | The generated tool index; /tools/<id>/tool.json is one tool's manifest with every input, default and format. |
/info/skills/lolly/SKILL.md | The agent skill: one page an agent loads to drive Lolly across every surface, with references for URL mode, the surfaces, the whole catalogue and the three document tools (chart, design, deck). |
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.
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. Same inputs → same output, always - so results are reproducible, auditable and version-controllable.
signed by Lollyvector SVGPrüfen Sie es selbstGet the signed file1 path~1.4k nodes12 KBTry it in the app
Use Lolly to generate the conference badge:
tool: event-name-badge
eventName: "KubeCon 2026" firstname: "Ada" lastname: "Lovelace" company: "SUSE"
Return the file URL.
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:
npm run cli -- event-name-badge # prints inputs, defaults, and supported formats
npm 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.)
| Param | Effect |
|---|---|
format | Output format (png, svg, pdf, mp4, …) |
export | Presence flag - render and download immediately on load |
copy | Presence flag - copy the result to the clipboard on load |
width / w, height / h | Output size (value in unit) |
unit, dpi | Physical sizing (mm/cm/in/pt) + raster resolution |
bleed, marks | Print bleed and crop marks |
profile | Colour profile - raster ICC (srgb/none) or CMYK press condition |
filename, output | Download filename / CLI output path |
password | Lock the exported PDF |
_v | Pin the tool version for stable output |
slot | Open 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
- Interactive / in a browser session: append
&export(or©) - the file downloads (or goes to the clipboard) on load. - Headless / server-side automation: use the CLI - it's the same parameter surface and writes bytes to a file or stdout:
``bash npm run cli -- qr-code --url=https://suse.com/kubecon --color=0c322c \ --export=svg --output=./qr.svg ``
(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:
- Non-exporting utilities (
countdown-timer,strip-data,text-helper,compress-pdf) setrender.export: false-&export/©are no-ops. (color-paletteis not one of them: the community Palette Lab declaressvg,png,jpg,webp,csv,json,css,scss,gplandase. A brand pack can narrow any community tool's declared formats, so read the manifest - orlolly_describe_tool- rather than assuming.) - Experimental tools (those with
status: "experimental"in their manifest) watermark every export until they're promoted, so their output isn't press-clean yet. - File-input tools like
strip-datatransform the user's own bytes in memory; they need a file the agent can't supply through a URL (see the device-local note below).
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:
| Tool | Does |
|---|---|
lolly_list_tools | List / search the catalogue (by text, status, category, format, capability). |
lolly_describe_tool | One tool's full input JSON Schema, built-in templates/presets, supported formats, canvas size and examples. |
lolly_validate | Validate 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_measure | Compile once, inspect the semantic document and measure it without rasterising. |
lolly_build_url | Build a shareable, editable link + raw render URL - without rendering. |
lolly_render | Render a tool to a file (returns the bytes plus the editable link). |
lolly_transform | Run an on-device file utility (strip-data, compress-pdf) on a file you supply. |
lolly_redact | Redact regions of an image, SVG or PDF on-device - covered content is destroyed and the file rebuilt, so nothing is recoverable underneath. |
lolly_verify | Verify a file's Content Credentials (C2PA) - the verdict, signer identity, edit history and embedded metadata. Checked in-process, never stored. |
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" } }
]
}
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:
- Vector -
svg,pdf,pdf-cmyk,eps,emf,dxf(cut file) - Raster -
png,jpg,webp,avif,tiff,cmyk-tiff,ico - Animation -
gif,apng,webp-anim,svg-anim(vector),webm,mp4 - Documents & data -
pptx(PowerPoint),html,md,txt,json,csv,ics,vcf,zip
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 recommended endpoint is the full one - https://mcp.lolly.tools/mcp (a browser-free serverless endpoint at https://lolly.tools/api/mcp also exists, for vector/data output only). Connect either one of two ways - both authenticate against the same shared access token, which your Lolly operator holds (it is never printed in a link or a log). Full reference: the MCP Server page.
A custom connector (OAuth). The endpoint is also a stateless OAuth 2.1 authorization server, so it drops straight into any MCP client that supports custom connectors:
- 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.) - Leave the OAuth Client ID / Secret blank - the server registers your client automatically (dynamic client registration).
- 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 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
- Quality doesn't drift. Layout, type, colour and spacing are structural - hard-coded by the tool author, not prompted. A lazy model can't degrade them.
- Cheap. A parameterised URL is a handful of tokens versus thousands for a brief + generation - and the result is production-grade.
- Deterministic & auditable. Every output is reproducible from its inputs; pin
_vfor byte-stable results across tool updates. - Private by default. It runs on the device - no customer data sent to a third-party model or service.
Tips
- Pin
_vin automation so a tool update can't silently change output. - Compact encodings: some tools define short
urlKeyaliases and tilde-delimited arrays to keep links short - see URL Mode. - Call
lolly_validatebefore rendering. MCP compile/build/render calls now reject unknown fields and invalid values with exact paths. Hand-authored URL mode remains tolerant for backward compatibility, so validate explicitly before emitting a raw URL yourself. - Device-local images (user uploads) can't travel in a URL - agents should reference catalog assets by id, not local uploads.
- One tool, many outputs: change
format/unit/widthto emit the same design as SVG, print PDF and social MP4 from one set of inputs. - Portable embed URL: an agent can emit
https://lolly.tools/tool/<id>.<ext>?<inputs>(image extensionspng,jpg,jpeg,webp,svg, plus animatedgifandapng) and drop it straight into HTML as an<img src=…>. Inside the live web view it renders locally - nothing fetched. On the open web the same URL is served for real by deployments that leave hot-link renders enabled - live onlolly.art, switched off onlolly.tools- for the browser-free formats (svgfor every tool,pngfor SVG-native ones), so those links work as plain hot-linked images in READMEs and wikis - see MCP Server for that endpoint's scope and current state.