Skip to main content
Glama

pixoo_render_html

pixoo_render_html
Idempotent

Render HTML at LED panel size in a headless browser, capture up to 800 frames for animation, and optionally push to a Pixoo display.

Instructions

Render an HTML page — a full document or a body fragment, with inline CSS, Canvas, SVG, or WebGL — in a headless browser at the panel size, and optionally push it to the display. Animate it by capturing up to 800 frames on a virtual clock that advances speed ms per frame: window.render(t, frame), when the page defines it, runs before each capture with t = frame / frames, so periodic motion loops seamlessly; CSS animations, requestAnimationFrame, timers, Date, and performance.now follow the same clock, so every frame is deterministic. The page loads nothing from the network and starts no workers; a page with no background renders on black, which the panel shows as unlit. Every page gets a pixoo global before its own scripts run: pixoo.text, pixoo.icon, and pixoo.palettes draw crisp bitmap text, gradient palettes, and icons exactly as pixoo_compose_scene does. Returns the captured result as an image content block — for an animation, a grid of its frames — and the page's uncaught and console errors as pageErrors. Run pixoo_design_brief with topic "html" first for loop, clock, sampling, legibility, and pixoo runtime guidance.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
htmlYesThe page to render: a full HTML document or a body fragment, up to 500,000 characters, served with <!doctype html> prepended. It lays out in a square viewport one CSS pixel per LED (64×64 on a Pixoo-64). Inline scripts and styles run and data: and blob: URLs load; a network URL is blocked and listed in pageErrors.
pushNoPush to device (default: true).
speedNoMilliseconds per frame (10–2000, default: 150): how far the virtual clock advances between captures, and how fast the animation plays.
finishNoReduce the image to a palette before it reaches the panel: exactly one of colors (2–256, built from the image) or palette (1–256 hex or named colors), plus dither. Transparent pixels stay unlit and are not counted. The preview shows the finished frame.
framesNoNumber of frames to capture (1–800, default: 1). At frame i, window.render gets t = i / frames and performance.now() reads i × speed. Up to 40 push frame by frame; more play as one GIF the device downloads from this host, so the device must reach it (behind NAT or a firewall, set PIXOO_SERVE_HOST and PIXOO_SERVE_PORT), and speed rounds to the nearest 10 ms.
outputNoAbsolute, already-normalized path to save the first frame to as a PNG. Replaces the PIXOO_OUTPUT_DIR auto-save for this call, so outputFiles holds only this path.
samplingNonative (default) captures one CSS pixel per LED. supersample renders at 8× and averages each 8×8 block into one LED, so transforms, text, SVG, and canvas shade smoothly; a plain box still snaps to whole CSS pixels (left: 0.5px lands on one LED), so move it with transform for sub-pixel motion.native

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
errorNoPresent when the call failed. Absent on success.
framesNoNumber of frames captured (1 for a still, 2–800 for an animation).
noticeNoWarning or informational notice about the render or push.
pushedNoTrue when the device acknowledged the push; past 40 frames, once it accepted the GIF play, requested the file, and the whole file was handed to the OS to send (the device does not confirm receipt). False when push: false.
pageErrorsNoThe page's uncaught errors, console.error output, and blocked request URLs, in the order they arrived: the first 20, each cut to 500 characters. Empty when the page reported none.
deviceStateNoDevice state after the push. Absent when push: false.
outputFilesNoAbsolute paths to saved output files: the output path when set, otherwise the PIXOO_OUTPUT_DIR auto-save (PNG for a still; for an animation an 8× GIF, or past 40 frames the panel-size GIF the device downloads). Absent when neither applies.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Addedv1.4.0

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Far exceeds the (already low) bar set by idempotentHint/destructiveHint: it discloses the network-free sandbox, no workers, black-background default, deterministic virtual clock semantics, the 800-frame cap, the >40-frame GIF-requires-host-reachable behavior with PIXOO_SERVE_HOST, speed rounding, and that uncaught/console errors come back as pageErrors. That is rich operational context an agent could not infer from annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose is front-loaded in the first clause and every sentence carries substance. It is dense and lengthy, with a few clauses (e.g. the full re-derivation of the clock rules) that partly restate what parameters later say, keeping it just shy of a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter, side-effecting renderer this is complete: it explains the execution sandbox, the animation model, the push/GIF delivery constraint, and the return shape (image content block, frame grid, pageErrors) — and an output schema exists, so return values needn't be spelled out further.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage the baseline is 3, but the description adds cross-parameter meaning the schema lacks: how window.render(t, frame) is invoked, that t = frame/frames produces seamless looping, and how the same clock drives CSS/rAF/timers. The pixoo global injection and network-block behavior also deepen parameters beyond their literal schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

It uses a precise verb+resource ('Render an HTML page ... in a headless browser at the panel size') and enumerates the supported content types (inline CSS, Canvas, SVG, WebGL, animation). It also differentiates itself from siblings by name, calling out that the pixoo global draws 'exactly as pixoo_compose_scene does' and routing to pixoo_design_brief. An agent can select it without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context for the animation path (capture frames for a loop, run pixoo_design_brief first) and the push toggle, but it never states an explicit when-not or a direct either/or against a sibling such as pixoo_push_image. Usage is strongly implied rather than laid out as alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.