The Lolly MCP server

Lolly ships a native Model Context Protocol server - a single endpoint any MCP client (an agent runtime, an IDE, a CLI, a hosted assistant) connects to directly. It exposes the tool 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. Because tools sync to the server as data, new tools appear with no server update.

It is the programmatic sibling of driving Lolly from a URL: same render path, same reproducible output - just reached over MCP instead of a hand-built link.

Two hosted endpoints

The render path has two tiers, so there are two endpoints. They share the same access token and the same tools - the only difference is which output formats each can produce.

EndpointTierProduces
https://mcp.lolly.tools/mcpFull (headless browser)Everything - vector, all raster (png/jpg/webp/…), print PDF (incl. CMYK + crop marks), and animation/video (gif/apng/webm/mp4).
https://lolly.tools/api/mcpLightweight (serverless, no browser)Vector (svg/emf/eps/eps-cmyk/dxf), data/text formats (html/md/txt/json/csv/ics/vcf), and png for SVG-native tools. (Print PDF needs the full endpoint's browser.)

Use the full endpoint (mcp.lolly.tools) unless you have a reason not to - it is a superset. The lightweight endpoint runs browser-free on the same infrastructure as lolly.tools, and is handy for quick vector/data work.

A render on either endpoint is byte-for-byte what a user's export produces - the server honours the full parameter contract (width/height/unit/dpi/colour profile/PDF password), and never watermarks or embeds anything a user's own download wouldn't.

Hot-linkable render URLs (no auth)

Alongside the authenticated MCP endpoints, lolly.tools answers the canonical embed URL directly:

GET https://lolly.tools/tool/<tool-id>.<ext>?<inputs>

This is the same "raw render URL" lolly_build_url returns - drop it into a README, wiki, Notion page or dashboard as an <img src=…> and it serves real bytes, no token needed. Its scope is deliberately narrow:

Self-hosters who don't want a public render surface can switch the route off entirely with LOLLY_DISABLE_RENDER_GET=1 - every /tool/<id>.<ext> URL then returns 404.

The six tools

ToolDoes
lolly_list_toolsList / search the catalogue (by text, status, category, format, capability).
lolly_describe_toolOne tool's full input JSON Schema, supported formats, canvas size, and examples.
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_verifyVerify a file's Content Credentials (C2PA): was it genuinely made with Lolly, who signed it, and has it changed since export. Returns the verdict, signer identity, edit history and embedded metadata (including any AI-generated declaration and appended-data flags) - the same C2PA verifier as the CLI's lolly validate. (The web verify page's pixel-level reads - the Lolly Imprint, SEAL, the opt-in deep scan - are interactive, web-only.) The file is checked in-process and never stored.

The intended flow is lolly_list_toolslolly_describe_tool (read the exact input schema) → lolly_render; lolly_verify closes the loop when an agent needs to prove a file it holds is an untouched Lolly export.

Any format, transparently

lolly_render returns whatever format the tool declares - the server decides 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 shape is identical either way. Animation, print PDF and HTML-layout raster require the full endpoint.

Resources - brand context without a render

Agents shouldn't guess asset ids or brand colours. Alongside the callable tools, the server exposes read-only MCP resources:

ResourceContents
lolly://catalogThe full generated tool index.
lolly://assetsEvery catalog asset id with its type, name, tags and formats - enumerate here first, so you never hallucinate an id.
lolly://tokensThe brand's design tokens (DTCG): named colour swatches with CMYK.
lolly://tool/{id}One tool's manifest summary + input JSON Schema + examples.
lolly://tool/{id}/previewThe tool's committed catalog preview (SVG), where one exists.
lolly://asset/{id}A catalog asset (logo, palette, font) resolved to bytes.

The intended pairing: read lolly://assets once, then pass a real id to any asset-typed input in lolly_render.

Prompts - guided invocations

The server also publishes MCP prompts, for clients that surface them as slash-commands or quick actions:

Connect a client

Both endpoints authenticate against the same shared access token, which your Lolly operator holds. It is never printed in a link or a log.

A custom connector (OAuth)

The endpoint is 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.

Then ask the agent to "list the Lolly tools" or "render the color-block tool as a PNG."

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>" }
    }
  }
}

A quick smoke test with curl (expect a JSON list of the six tools; no token returns 401):

curl -s -X POST https://mcp.lolly.tools/mcp \
  -H "authorization: Bearer <your-access-token>" \
  -H "content-type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

During local development you can also run the server over stdio - no token needed. See the Build Guide.

Authentication & security

Self-host it

The full endpoint is the one part of Lolly that is a server-side add-on, not an on-device component - producing the full format range means driving a headless browser against a built web shell, which runs as a hosted service (a container or worker), not offline or at the edge. The on-device shells - web PWA, desktop, mobile and CLI - remain the offline / air-gapped path.

You can run the full server yourself - including fully air-gapped - as a container that ships the scoped Chromium and a prebuilt web shell. See the Build Guide and the deployment notes in services/mcp/.

Why this beats prompting an image model