pixoo-mcp-server
Allows using Cloudflare R2, KV, or D1 as swappable storage backends for managing server data and display assets.
Enables loading, resizing, and pushing JPEG images directly to Divoom Pixoo LED matrices.
Includes support for OpenTelemetry instrumentation to provide observability and monitoring of server operations.
Provides support for using Supabase as a storage backend provider for server data and configurations.
Supports loading and pushing SVG vector graphics to Divoom Pixoo devices with automatic resizing to the display grid.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@pixoo-mcp-serverdisplay 'Meeting in Progress' in red scrolling text and set brightness to 50"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Tools
Seven tools covering the full display pipeline — from quick styled text to full layered scene composition, device control, and initial setup:
Tool | Description |
| Render styled text (theme, gradient, shadow, outline, auto-fit) onto the display and push it. Returns the rendered frame as an image. |
| Compose a full scene: layered elements (text, icons, widgets, shapes, bitmaps, images, sprites) with per-element effects and keyframes, static or animated. Returns the rendered scene as an image. |
| Load an image (absolute local path or https URL), resize it to the LED grid, and push it. Returns the downsampled result as an image. |
| Set or clear a device-native scrolling text overlay. Uses device-rendered fonts; overlays persist across channel switches until cleared. |
| Read or change device state: brightness, screen on/off, channel, or clock face. Call with no params for a status read. |
| Find Pixoo devices on the local network via Divoom's cloud discovery endpoint. Run once during setup to find device IPs. |
| Return craft guidance and live device context for a design topic. Covers legibility rules, palette discipline, layout zones, animation budget, and pre-filled next-tool suggestions. |
pixoo_display_text
The primary tool for text-only display. Covers the 80% case — styled text with quality defaults.
Named scene themes set background gradient and text palette in one parameter (
midnight,ember,claude,ice,neon,forest,mono)Style block: gradient palette ramps (
ember,ice,neon,fire,lavender,claude,mono), drop shadow, 1px outline for legibility, integer scale multiplier for block-letter weightSemantic positioning:
x: "center",y: "bottom"— no manual pixel mathAuto-fit overflow: tries 5×7 → 3×5 → scroll; every fit decision reported in
layout[]Returns the rendered frame as an image content block so you see it immediately
Optional brightness convenience parameter applied before push
pixoo_compose_scene
Full scene composition with the complete element vocabulary.
Layered elements rendered back-to-front:
text,icon,rect,circle,line,progress,sparkline,bitmap,pixels,image,spriteNamed icons from the built-in registry (weather, arrows, status, media) or custom SVG path
Dashboard widgets:
progressbar with gradient fill and optional label;sparklinemini chart (line or bar, auto-scaled)Animation: named effect presets (
float,scroll-left,scroll-right,pulse,blink,twinkle,drift,fade-in,fade-out) or raw keyframe arrays — 1–40 frames, configurable speedPer-element opacity and
visibleflag; images at https URLs fetched server-side to a temp fileReturns a preview image (static: PNG; animated: labeled contact-sheet PNG + GIF saved to disk)
pixoo_push_image
Push any image to the display with control over the downsampling.
Accepts absolute local paths and https URLs
Three fit modes:
contain(letterbox),cover(crop to fill),fill(stretch)Three resize kernels:
nearestfor pixel art,lanczos3for photos,mitchellfor a balanceReturns the exact 64×64 result as an image block — you see what the display received
pixoo_overlay_text
Device-native scrolling text overlay — persists across channel switches.
115 device-rendered font IDs (0–114)
Up to 20 independent overlay slots (IDs 0–19)
Configurable scroll direction, speed, and alignment
Clears with
mode: "clear"— overlays survive channel changes until explicitly removedNot previewable (device-rendered); for styled previewable text use
pixoo_display_text
pixoo_design_brief
The orientation tool. Run before authoring any scene to get grounded in 64px craft constraints.
Six topics:
text,scene,dashboard,animation,pixel-art,troubleshootingReturns legibility floors, palette discipline, layout zones, animation budgets, and common pitfalls
Merges live device state (reachable, channel, brightness, screen) into the response
Pre-filled
nextToolSuggestionswith ready-to-use arguments based on current device state
Related MCP server: Piskel MCP Server
Resources
Type | Name | Description |
Resource |
| Live snapshot of the connected Pixoo display: reachable, channel, brightness, screen state, and display size |
Resource |
| Theme and palette registry with background gradients, default text palettes, accent colors, and swatch values |
Resource |
| Built-in icon names organized by category (weather, arrows, status, media) |
Resource |
| Long-form 64px craft guide: legibility floors, palette discipline, layout zones, animation budget, and known device behaviors |
All resource data is also reachable via tools. pixoo_design_brief surfaces the design guide content per topic; pixoo_control_device returns live device state equivalent to pixoo://device/status.
Features
Built on @cyanheads/mcp-ts-core:
Declarative tool and resource definitions — single file per primitive, framework handles registration and validation
Unified error handling — handlers throw, framework catches, classifies, and formats
Pluggable auth:
none,jwt,oauthSwappable storage backends:
in-memory,filesystem,Supabase,Cloudflare KV/R2/D1Structured logging with optional OpenTelemetry tracing
STDIO and Streamable HTTP transports
Pixoo-specific:
Requires a Divoom Pixoo LED matrix display on the local network; primary target is the Pixoo-64 (16 and 32 also supported)
All composition happens in an RGBA canvas pipeline on the host (
@cyanheads/pixoo-toolkit) — the device receives final RGB frames, never raw drawing commandsStyled text engine: gradient palette ramps, drop shadows, outlines, integer scale, semantic alignment — no manual pixel math or bitmap letterforms required
Push pacing: device commands serialized with a configurable minimum inter-push interval (default 1000ms) to prevent device freezes
Every
PixooResultchecked —pushed: truemeans the device acknowledged witherror_code: 0, never "I tried"Animation capped at 40 frames (device instability beyond this); contact-sheet PNG preview for animations (GIF inconsistent across MCP clients)
Local transports only —
sharpimage processing doesn't run on Cloudflare Workers
Agent-friendly output:
Preview-as-content: render tools return the upscaled (8×, 512px) output as an image content block — the calling model sees exactly what was drawn, before and after push
Layout transparency: every silent renderer decision (font fallback, truncation, scroll engaged, element clipped) reported in
layout[]so agents can inspect and refineDevice truth:
pushedreflects the device ACK;deviceStatepost-push flags visibility issues (screen off, brightness ≤ 10, wrong channel) as enrichment notices rather than failuresGraceful degradation: render succeeds and returns the preview even when the device is unreachable — the agent keeps its work
Getting started
Requirements: A Divoom Pixoo display (Pixoo-64, Pixoo-32, or Pixoo-16) on the same local network as the server. Run pixoo_discover_devices to find its IP, then set PIXOO_IP in your server configuration.
Add the following to your MCP client configuration file:
{
"mcpServers": {
"pixoo-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/pixoo-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"PIXOO_IP": "192.168.1.50"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"pixoo-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/pixoo-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"PIXOO_IP": "192.168.1.50"
}
}
}
}Or with Docker:
{
"mcpServers": {
"pixoo-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "PIXOO_IP=192.168.1.50",
"ghcr.io/cyanheads/pixoo-mcp-server:latest"
]
}
}
}For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 PIXOO_IP=192.168.1.50 bun run start:http
# Server listens at http://localhost:3010/mcpPrerequisites
Bun v1.3.2 or higher (or Node.js v24+).
A Divoom Pixoo LED matrix display on the local network (Pixoo-64, Pixoo-32, or Pixoo-16). Discovery tools and pure-render tools (
push: false) work without a configured device.
Installation
Clone the repository:
git clone https://github.com/cyanheads/pixoo-mcp-server.gitNavigate into the directory:
cd pixoo-mcp-serverInstall dependencies:
bun installConfigure environment:
cp .env.example .env
# edit .env and set PIXOO_IPConfiguration
All configuration is validated at startup via Zod schemas in src/config/server-config.ts. Key environment variables:
Variable | Description | Default |
| Device IP address on the local network. Required for device tools ( | — |
| Display size in pixels: |
|
| Directory for auto-saving preview PNG and GIF files. When unset, previews are returned in-response only. | — |
| Minimum interval between device pushes in milliseconds. Prevents device freeze from rapid-fire commands. |
|
| Transport: |
|
| HTTP server port. |
|
| Authentication: |
|
| Log level ( |
|
| Directory for log files (Node.js only). |
|
| Storage backend: |
|
| Enable OpenTelemetry instrumentation (spans, metrics, completion logs). |
|
See .env.example for the full list of optional overrides.
Running the server
Local development
Build and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:httpRun checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t pixoo-mcp-server .
docker run --rm -e PIXOO_IP=192.168.1.50 -p 3010:3010 pixoo-mcp-serverThe Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/pixoo-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Path | Purpose |
|
|
| Server-specific environment variable parsing and validation with Zod. |
| Tool definitions ( |
| Resource definitions ( |
|
|
| Pure rendering pipeline: element renderers, styled-text engine, themes, icons, effect compiler, preview encoding. No device dependency. |
| Unit and integration tests mirroring |
Development guide
See CLAUDE.md/AGENTS.md for development guidelines and architectural rules. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storageThe renderer (
src/renderer/) is pure — no device dependency, testable without hardwareAll device calls go through
PixooService; everyPixooResultis checked
Contributing
Issues and pull requests are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
Maintenance
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/cyanheads/pixoo-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server