MCP server for rendering content to e-ink displays (Waveshare EPD modules). Supports drawing primitives, text, images, and structured dashboard layouts.
Server has well-structured tool definitions with explicit Pydantic schemas and comprehensive parameter documentation. All 4 tools have descriptions and input schemas. However, descriptions are verbose (exceeding 200 chars for draw/render_layout), parameter descriptions lack actionable constraints (e.g., no min/max for numeric fields), and error handling guidance is absent. Output schemas are not documented. Tool naming is clear and verb-based (get_, clear_, draw, render_). No security issues detected (no secrets in params). Composition is sound, each tool has a single responsibility.
Clear the eink display to white.
Render drawing elements onto the eink display. TOOL SELECTION GUIDE — choose the right approach before calling: • Artistic / scenic content (landscapes, illustrations, portraits, animals, nature scenes, abstract art): generate the image externally and display it via an `image` element. Do NOT attempt to approximate art with primitives. • Structured / geometric content (charts, diagrams, icons, UI widgets, technical drawings): use the primitive elements (rect, line, ellipse, text). • Mixed content: combine an `image` element as background with text/rect overlays on top. Element types and their fields: image: { type, path, x=0, y=0, width=null, height=null } — PREFERRED for any pictorial or artistic content. path must be an absolute path to a PNG/JPEG/SVG/Pillow-readable file. SVG files are rasterised automatically via cairosvg. width/height are optional; omit both to use the file's native size. text: { type, text, x, y, size=24, bold=false, fill=0, font=null, align="left" } rect: { type, x0, y0, x1, y1, outline=0, fill=null } line: { type, x0, y0, x1, y1, fill=0, width=1 } ellipse: { type, x0, y0, x1, y1, outline=0, fill=null } progress_bar: { type, x, y, width, height=12, value, fill=0, background=240, outline=100 } divider: { type, y, fill=0, width=1, margin=20 } size accepts integers or named strings: title(34) large(28) label(19) value(17) small(14) tiny(12). align: "left"=x is left edge, "center"=x is center point, "right"=x is right edge. progress_bar value: 0.0–1.0 fill fraction. fill/outline/background: 0=black, 255=white, 0–255 greyscale. rotation: omit to use EINK_ROTATION env var; only pass to override. Values: 0, 90, 180, 270. background: canvas colour, default 255 (white).
Return the eink display dimensions and available named font sizes.
Verbose tool descriptions exceed 200 chars (draw: ~800, render_layout: ~600). LLM token waste and reduced clarity. Descriptions should be 50 - 200 chars with tool selection guidance in separate parameter docs.
No output schema documentation. Callers cannot predict response structure. Document return types for all tools (e.g., get_display_info returns {width: int, height: int, named_font_sizes: dict}).
Numeric parameters lack min/max constraints. rotation accepts 0|90|180|270 but no enum; background accepts 0 - 255 but no range documented; element coordinates unbounded. Add explicit constraints in descriptions and JSON Schema.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 59 | <=2025-11-25 | v2 |
Render a structured dashboard layout onto the eink display. TOOL SELECTION GUIDE: • Use render_layout for dashboard-style output: stats, text lists, charts, timelines, activity summaries. Sections auto-stack — no coordinate math. • Use draw() instead when you need pixel-precise positioning, layered elements, or a full-canvas artistic image (via its `image` element type). • For pictorial/scenic content inside a layout (e.g. a photo with a caption), use an `image_block` section — supply a pre-existing image file path. Sections stack vertically — no x/y coordinate math required. Section types: header: { type, title, subtitle=null } divider: { type, light=false, bold=false, margin_before=4, margin_after=6 } stat_block: { type, label, value=null, progress=null, detail=null, badge=null } text_row: { type, left=null, right=null, size="value", bold=false, fill=0 } spacer: { type, height=10 } bar_chart: { type, data=[{label, value},...], title=null } image_block: { type, path, width=null } — use for pictorial/scenic content; path must be an absolute path to a PNG/JPEG/Pillow-readable file. bar_chart must be the last section — it fills all remaining vertical space. progress: 0.0–1.0 fill fraction. size: integer pixels or named string (title, large, label, value, small, tiny).
No error handling guidance. If an image path is invalid, file not found, or SVG rasterization fails, the tool should return actionable recovery hints (e.g., 'Image not found at /path/to/file. Verify path is absolute.').
draw and render_layout descriptions embed extensive element/section type documentation inline. Move to separate reference docs or parameter descriptions; keep tool description to ~100 chars with a 'See parameter docs for element types' pointer.