An MCP (Model Context Protocol) server that lets AI assistants draw pixel art on iDotMatrix LED displays over Bluetooth.
Connect your iDotMatrix display to Claude, ChatGPT, or any MCP-compatible client and ask it to draw pictures, icons, animations, dashboards — anything that fits on a 16x16, 32x32, or 64x64 pixel grid.
The server maintains an in-memory pixel canvas that matches your display's resolution. AI assistants interact with the canvas through MCP tools — drawing shapes, filling colors, rendering text — then push the finished frame to the physical display over BLE.
AI Assistant ──MCP tools──> idotmatrix-mcp ──BLE──> iDotMatrix Display
(canvas buffer)
Workflow:
- The assistant calls
discover_devicesto find nearby iDotMatrix displays - It connects with
connect_device, specifying the screen size - It draws on the canvas using drawing tools (or
draw_batchfor multiple operations at once) - It calls
get_previewto see an ANSI block-art preview in the chat - It calls
send_to_displayto push the frame to the physical device
- Node.js 18+
- macOS (BLE support via the
idotmatrixnpm package — uses Noble under the hood) - An iDotMatrix LED display powered on and within Bluetooth range
git clone https://github.com/nailan/idotmatrix-mcp.git
cd idotmatrix-mcp
npm install
npm run buildAdd to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"idotmatrix": {
"command": "node",
"args": ["/absolute/path/to/idotmatrix-mcp/dist/index.js", "--stdio"]
}
}
}Add to your Claude Code settings (.claude/settings.json or global):
{
"mcpServers": {
"idotmatrix": {
"command": "node",
"args": ["/absolute/path/to/idotmatrix-mcp/dist/index.js", "--stdio"]
}
}
}The server also supports Streamable HTTP transport for clients that don't use stdio:
node dist/index.js # defaults to http://127.0.0.1:8321/mcp
node dist/index.js --port=9000 # custom port| Tool | Description |
|---|---|
clear_canvas(color) |
Fill entire canvas with one color and reset |
get_preview() |
Return an ANSI block-art preview of the canvas |
list_colors() |
List all 48 named colors with hex values |
| Tool | Description |
|---|---|
draw_rect(x, y, width, height, color, fill?) |
Rectangle (filled by default) |
draw_circle(cx, cy, radius, color, fill?) |
Circle (filled by default) |
draw_ellipse(cx, cy, rx, ry, color, fill?) |
Ellipse with independent radii |
draw_line(x1, y1, x2, y2, color) |
Line between two points |
draw_triangle(x1, y1, x2, y2, x3, y3, color, fill?) |
Triangle (filled by default) |
draw_rounded_rect(x, y, width, height, radius, color, fill?) |
Rectangle with rounded corners |
draw_polygon(cx, cy, radius, sides, color, fill?, rotation?) |
Regular polygon (3-12 sides) |
draw_gradient(x, y, width, height, color_from, color_to, direction?) |
Linear gradient fill (vertical, horizontal, or diagonal) |
set_pixel(x, y, color) |
Set a single pixel |
flood_fill(x, y, color) |
Paint-bucket fill from a point |
draw_text(text, x, y, color, font_size?) |
Bitmap text (3x5 "small" or 5x7 "medium") |
| Tool | Description |
|---|---|
draw_batch(commands) |
Execute multiple draw commands in one call |
draw_batch accepts an array of command objects. Each object has a command field plus the same parameters as the corresponding individual tool. This is the most efficient way to compose scenes — one tool call instead of many round-trips.
[
{ "command": "clear", "color": "dark_blue" },
{ "command": "gradient", "x": 0, "y": 0, "width": 64, "height": 32, "color_from": "navy", "color_to": "sky_blue" },
{ "command": "circle", "cx": 48, "cy": 8, "radius": 5, "color": "yellow" },
{ "command": "ellipse", "cx": 20, "cy": 16, "rx": 10, "ry": 5, "color": "white" },
{ "command": "rounded_rect", "x": 10, "y": 40, "width": 44, "height": 16, "radius": 4, "color": "green" },
{ "command": "polygon", "cx": 50, "cy": 10, "radius": 6, "sides": 5, "color": "gold" },
{ "command": "text", "text": "HI", "x": 28, "y": 44, "color": "white" }
]Supported commands: clear, rect, circle, ellipse, line, triangle, rounded_rect, polygon, gradient, pixel, fill, text.
Execution stops on the first error and reports which command failed.
| Tool | Description |
|---|---|
discover_devices(timeout_seconds?) |
Scan for nearby iDotMatrix BLE devices |
connect_device(device_id, screen_size) |
Connect to a device (screen size: 16, 32, or 64) |
disconnect_device() |
Disconnect from the current device |
send_to_display() |
Push the canvas buffer to the connected display |
The server includes a curated 48-color palette optimized for LED displays. Use list_colors to see all options. Some highlights:
- Neutrals:
black,white,gray,dark_gray,light_gray - Warm:
red,orange,yellow,coral,salmon,pink,hot_pink - Cool:
blue,cyan,green,teal,sky_blue,purple,violet - Earth:
brown,tan,sand,skin,peach,dark_brown - Nature:
forest,dark_green,lime,spring,mint,olive
Gradients interpolate between any two palette colors, producing smooth intermediate shades not limited to the 48-color palette.
The server ships a drawing-guide prompt that gives the AI assistant context about the coordinate system, available tools, color palette, and pixel art tips. MCP clients that support prompts will make this available automatically.
- Origin
(0, 0)is the top-left corner - X increases rightward, Y increases downward
- Drawing outside bounds is silently clipped
npm run dev # run with tsx (no build step)
npm run build # compile TypeScript to dist/
npm run clean # remove dist/MIT