PLMHub boards
Server Details
Draw diagrams, build HTML pages and write Markdown in a live editor the user sees.
- Status
- Healthy
- Uptime
- 100.0% over the last 24 hours
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- ChatGPT
- –
- Claude
- –
TDQS
Scored across 5 tools
The tools have clearly distinct roles: open_board creates a board, read_board reads it, write_board replaces HTML/Markdown content, edit_text makes partial text-board edits, and draw handles doodle boards. The descriptions explicitly separate doodle operations from text-board operations, leaving little room for misselection.
Four tools follow a clear verb_noun pattern (open_board, read_board, write_board, edit_text), which is consistent and readable. The lone exception is draw, which is a standalone verb and does not follow the noun-suffix pattern.
Five tools is well-scoped for a board server with two board types. Each tool has a distinct role, and the large doodle operation surface is sensibly consolidated into the single draw tool rather than split into many tools.
The surface covers creation, reading, full replacement, partial editing, and doodle manipulation well. However, there is no visible operation for deleting, closing, listing, or renaming boards, leaving notable lifecycle gaps.
Available Tools
5 toolsdrawDraw on a doodle boardAInspect
Draw on a doodle board. The user sees each call appear live in the editor.
Doodle ops
A doodle is a board (default 1280 x 720 px, origin top-left, y grows down). Send ops as
{"ops": [...]}; they apply in order, all or nothing. The answer lists the ids each op
created, in order. Address elements by id; read the board for the ids it already has.
Positions: x, y is the CENTER of a shape or text, the top-left of a comment, the midpoint of a line. Omit them to place at the board's center. Later elements draw on top.
Create
{"op": "add", "role": "text" | "box" | "button" | "input" | "card" | "ellipse" | "line" | "image" | "comment" | "draw" | "triangle" | "diamond" | "star" | "frame", "x", "y", "w"?, "h"?, "id"?, ...style}Defaults (w x h): text 160 wide, box 180x110, card 240x150 (radius 12), button 150x46, input 220x44, ellipse 140x90, line 180 long, triangle 120x110, diamond/star 120x120, image 320x200 (needs "src": URL or data: URL), frame 360x240, draw needs "path". Pass your own "id" to address the element without reading back (it must be unused). Buttons and inputs are plain shapes: give them text withlabel.{"op": "draw", "path": "M 10 10 L 90 90", "stroke"?, "strokeWidth"?}freehand; path coordinates are board coordinates.{"op": "comment", "text", "x"?, "y"?, "w"?}a sticky note for the human.{"op": "label", "id": shapeId, "text", "fontSize"? = 16, "fill"?, "labelId"?}text centered inside a shape that follows it when the shape moves. Empty text removes it.{"op": "duplicate", "id", "newId"?, "dx"? = 20, "dy"? = 20}
Change
{"op": "update", "id", ...style}(fields below; "x"/"y"/"w"/"h" set position and size){"op": "move", "id", "dx", "dy"}or{"op": "move", "id", "x", "y"}; moving a frame moves its children too.{"op": "reorder", "id", "to": "front" | "back" | "forward" | "backward"}{"op": "delete", "id"}·{"op": "clear"}removes everything.
Style fields (add and update)
fill, stroke, backgroundColor (CSS colors) · strokeWidth · opacity 0..1 · angle (degrees) · radius (corner radius; or rx, ry) · borderStyle "solid" | "dashed" | "dotted" | "dashdot" or strokeDashArray [numbers] · shadow "none" | "soft" | "medium" | "hard", {color, blur, offsetX, offsetY} or null · gradient {"type": "linear" | "radial", "stops": [{"offset": 0, "color": "#6366f1"}, {"offset": 1, "color": "#ec4899"}], "coords"?: 0..1 units} (replaces fill) · flipX, flipY, skewX, skewY · text, fontSize, fontFamily, fontWeight, fontStyle ("italic"), textAlign, underline, linethrough, lineHeight, charSpacing, padding · name (layer name), visible, locked (true/false).
Structure
{"op": "group", "ids": [2 or more], "name"?, "groupId"?}returns the group id.{"op": "ungroup", "group": groupId}or{"op": "ungroup", "ids": [...]}.{"op": "wrap", "ids": [...], "direction"?, "justify"?, "align"?, "gap"?, "padding"?, "frameId"?}puts the elements in a new auto-layout frame and returns its id.{"op": "unwrap", "id": frameId}removes the frame and keeps its children.{"op": "reparent", "ids": [...], "frame": frameId}moves elements into a frame;"frame": nulltakes them out.{"op": "layout", "id": frameId, "mode"?: "block" | "flex", "direction"?: "row" | "col", "justify"?: "start" | "center" | "end" | "between", "align"?: "start" | "center" | "end" | "stretch", "gap"? = 16, "padding"? = 16, "wMode"?, "hMode"?: "hug" | "fixed", "w"?, "h"?}A flex frame lines its children up (row = left to right, col = top to bottom) and hugs them, or keeps the fixed w/h. A block frame leaves children where they are.{"op": "size", "id", "w"?, "h"?: "fixed" | "hug" | "fill", "minW"?, "maxW"?, "minH"?, "maxH"?}how a child of a flex frame sizes; fill shares the frame's spare room; null clears a min/max.
Board
{"op": "bg", "color": "#f8fafc"}or{"op": "bg", "src": imageUrl}(an image behind everything).{"op": "board", "w"?, "h"?, "autoH"?: true, "padding"?, "minH"?, "maxH"?}autoH grows the board to fit its content plus padding, within minH..maxH.
Errors name the failing op (ops[2] (move): ...): 400 for a bad field, 404 for an unknown
id, 409 for an id already in use. Fix that op and send the batch again.
Inputs: ops (required), board (required).
edit_textEdit an HTML or Markdown boardAInspect
Change part of an HTML or Markdown board without resending all of it. Ops (applied in order, all or nothing):
{"op": "write", "text": "..."} (replace everything)
{"op": "append", "text": "..."}
{"op": "replace", "find": "...", "replace": "..."} (find must occur exactly once)
Inputs: ops (required), board (required).
open_boardOpen a new boardAInspect
Open a new, empty board and get its link. Give the link to the user: they watch your work there and download it.
Inputs: kind (required).
read_boardRead a boardARead-onlyInspect
Read a board: its kind and current content (the Markdown or HTML text, or the doodle's elements with their ids, roles, boxes and styles).
Inputs: board (required).
write_boardReplace a board's contentAInspect
Replace everything on an HTML or Markdown board. HTML: one complete document with inline CSS and JS. Markdown: GitHub-flavored. For a doodle, use draw instead.
Inputs: board (required), content (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
Related MCP Connectors
Create, edit, read and review web presentations: slides, linked buttons, pictures, runnable code.
Create, edit, share and render real-time collaborative diagrams and mindmaps on livediagram.app.
Publish HTML, docs, slides and dashboards from your AI CLI; edit them live with people.
Create, read and edit architecture, flow and ER diagrams on a live canvas shared with your team.
Related MCP Servers
- AlicenseAqualityBmaintenanceGenerates diagrams, charts, HTML pages, and slide decks from text DSLs, enabling AI agents to embed visual assets into Markdown.855 npm1MIT
- AlicenseNot gradedqualityCmaintenanceEnables streaming hand-drawn Excalidraw diagrams with smooth viewport camera control and interactive fullscreen editing.MIT
- AlicenseNot gradedqualityCmaintenanceEnables MCP clients to create and live-update Excalidraw diagrams in batches, with preview links, checkpoint restoration, browser editing, and optional authenticated shared storage.3,204 npmMIT
- AlicenseNot gradedqualityDmaintenanceStreams hand-drawn Excalidraw diagrams with smooth viewport camera control and interactive fullscreen editing, enabling diagram creation via natural language.MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.