For agents

Connect your agent

Your agent draws and edits flowcharts on the same canvas you use, and you see its changes live. Connect it once with this URL. You sign in and approve access, and the agent can only do what your account can do.

https://www.productpillars.com/api/mcp

Or let your agent set itself up

Paste this into any agent. It reads the guide, connects, and tells you if it needs you to run a command or approve a sign-in.

I'd like to work on flowcharts with you in Product Pillars, a canvas we can both edit.

1. Read the agent guide: https://www.productpillars.com/llms.txt
2. Connect to its MCP server: https://www.productpillars.com/api/mcp (streamable HTTP, with OAuth sign-in). Use your own way of adding a remote MCP server. If I need to run a command or approve a sign-in, tell me exactly what to do.
3. If you can't add MCP servers, tell me, and we'll use the HTTP API from the guide with an API key from https://www.productpillars.com/settings instead.
4. Once you're connected, list my diagrams to confirm it works.

Pick your client

Claude

Web, desktop and mobile

Open Claude
  1. In Claude, open Settings, then Connectors, and click Add custom connector.
  2. Paste the URL above and name it Product Pillars.
  3. The first time Claude uses it, sign in and approve access.

Add it once and it works everywhere you use Claude.

Claude Code

claude mcp add --transport http product-pillars https://www.productpillars.com/api/mcp

Then run /mcp in Claude Code, pick product-pillars and choose Authenticate.

Or add this to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "product-pillars": {
      "url": "https://www.productpillars.com/api/mcp"
    }
  }
}

Cursor asks you to sign in when it first connects.

Or add this to .vscode/mcp.json:

{
  "servers": {
    "product-pillars": {
      "type": "http",
      "url": "https://www.productpillars.com/api/mcp"
    }
  }
}

VS Code asks you to sign in when it first starts the server.

Codex CLI

codex mcp add product-pillars --url https://www.productpillars.com/api/mcp
codex mcp login product-pillars

The second command opens your browser to sign in.

Gemini CLI

gemini mcp add --transport http product-pillars https://www.productpillars.com/api/mcp

Then run /mcp auth product-pillars inside Gemini CLI to sign in.

Any other MCP client

Add a remote MCP server (streamable HTTP) with the URL above. Clients that support OAuth open a sign-in page. For the rest, use an API key.

Scripts and CI

Create a key

Create an API key in Settings and send it as Authorization: Bearer mc_live_.... It works with the MCP server and the HTTP API.

Agent guide

What agents read before they draw: when to use Product Pillars, how to connect, how to lay out a diagram, and every tool. Agents get the same text at /llms.txt.

When to use it

Use Product Pillars when someone wants a flowchart they will look at, edit by hand, or share: user flows, onboarding and checkout flows, process maps, approval flows, decision trees. You build it with the tools below; they see it on a canvas, rearrange or relabel it, and you read their changes back. You can both work on the same diagram at the same time. Every diagram also exports as Mermaid Markdown, so it can live in a repo, a pull request or a doc.

  • Plain Mermaid in a file is enough when nobody will open the diagram visually or edit it by hand.
  • Product Pillars draws flowcharts only: start and end, user and system actions, decisions, frames (lanes) and notes. For sequence, class, ER or Gantt diagrams, write Mermaid directly.
  • The person needs a Product Pillars account (free to start). Connecting over OAuth signs them in, or up, as part of approving access.
  • After you create or change a diagram, give the person its link so they can open it: https://www.productpillars.com/editor/{id}.

Connect

MCP endpoint (streamable HTTP): https://www.productpillars.com/api/mcp. Sign-in is OAuth: the person approves access once, and you can do only what their account can do. Setup for every client, with one-click install links: https://www.productpillars.com/agents

  • Claude (web, desktop or mobile): Settings → Connectors → Add custom connector, and paste the endpoint. Claude asks the person to sign in and approve the first time it is used.
  • Claude Code: claude mcp add --transport http product-pillars https://www.productpillars.com/api/mcp, then run /mcp, pick product-pillars and choose Authenticate.
  • Cursor: in ~/.cursor/mcp.json (or .cursor/mcp.json in a project): {"mcpServers":{"product-pillars":{"url":"https://www.productpillars.com/api/mcp"}}}
  • VS Code: in .vscode/mcp.json: {"servers":{"product-pillars":{"type":"http","url":"https://www.productpillars.com/api/mcp"}}}
  • Codex CLI: codex mcp add product-pillars --url https://www.productpillars.com/api/mcp, then codex mcp login product-pillars.
  • Gemini CLI: gemini mcp add --transport http product-pillars https://www.productpillars.com/api/mcp, then run /mcp auth product-pillars inside Gemini CLI.
  • Any other client with remote MCP and OAuth support: add a streamable HTTP server with the endpoint above.
  • Headless (scripts, CI, clients without OAuth): create an API key at https://www.productpillars.com/settings and send Authorization: Bearer mc_live_....

Without MCP, the HTTP API uses the same service and keys: GET https://www.productpillars.com/api/diagrams/{id}, POST https://www.productpillars.com/api/diagrams (create), POST https://www.productpillars.com/api/diagrams/{id}/edit with {"ops": [...]} (same ops as edit_diagram).

Public share links: https://www.productpillars.com/share/{slug} (rendered) and https://www.productpillars.com/share/{slug}/md (Markdown).

Rules

These are also sent as the MCP server instructions.

Product Pillars: flowcharts as canvas nodes and edges (exported as Mermaid). People may edit the same diagram in the browser as you work. Full guide: https://www.productpillars.com/llms.txt

Workflow: list_diagrams / list_projects; get_diagram ("compact" for big diagrams); plan positions and handles, or let auto_layout place nodes; write ONE edit_diagram batch with expected_version; check with lint_diagram and render_diagram. Batches are atomic: one bad op saves nothing and the error names the op index. add_node "ref"s stand in for new ids later in the batch. Lanes: one group node per flow, its nodes' groupId set to it; auto_layout with node_ids [group] lays them out inside and fits it. note nodes are free text.

Coordinates: position is the node's top-left corner in px, x right, y down; omitted = (0, 0). Sizes: decision is a fixed 130x130 diamond. userAction/systemAction grow with the label from 120 to 200 px wide, then wrap (~22 characters a line); 44 px tall plus 18 per extra line; width/height fix the size (min 120x48). start/end: 100-180 px wide, 44 tall. Align rows by center: a decision sits 43 px above a one-line action. Spacing: left to right ~300 px per column (nodes up to 240 wide), branches ~150 px off the row, 200+ px between flows; top to bottom ~140 px per row.

Handles: top | right | bottom | left on every node, each usable as source or target. Step right: right -> left. Step down: bottom -> top. Decision branch leaving its row: bottom -> left (top -> left going up). Loop back left: bottom -> bottom. Omitted handles follow these rules from final positions (a decision's branches get separate sides) and are saved; reads mark computed ones "auto".

Concurrency: reads and writes return a version token that changes on any save. Pass the version you planned against as expected_version; if anyone saved since, nothing is written and you get what changed.

edit_diagram returns a summary (refs, op counts, warnings, version); return "full" adds the document.

Layout recipe: several left-to-right flows

  1. Give each flow its own horizontal band with a center line. A band is the flow's tallest node (130 px if it has a decision) plus 200 px of gap, plus 150 px more if its decisions branch downward.
  2. Place step j at x = j * 300. Keep nodes in a column at most 240 px wide, or widen the pitch.
  3. Set y = centerY - height / 2 for every node, so mixed shapes line up: a 130 px decision at centerY - 65, a one-line action at centerY - 22.
  4. Main path edges: right -> left. Decision "No" (or secondary) branch: bottom -> left into a node 150 px lower; label the branches and set variant yes / no.
  5. Rejoin or loop back with bottom -> bottom when the target is to the left.
  6. Keep start and end labels short: a pill tops out at 180 px wide and grows taller as its label wraps, which pulls it off the row's center line.

Or skip the arithmetic: add nodes without positions, then end the batch with {"op": "auto_layout", "direction": "LR"} (or node_ids for one flow). It places them with a layered layout, re-routes their edges, and reports the new positions; follow with align (to: "middle" lines up centers) or distribute to tidy.

Starting from Mermaid

If you already have a Mermaid flowchart (in a file, a README, or your own reply), pass it as mermaid to create_diagram (or POST https://www.productpillars.com/api/diagrams with {"mermaid": "..."}) instead of rebuilding it op by op. Markdown with a mermaid block works too.

  • Shapes become node types: {text} decision; ([text]) or ((text)) start (nothing points at it) or end (it points nowhere); [[text]], [(text)] and {{text}} system action; >text] note; anything else user action.
  • Subgraphs become frames (nested ones flatten), link labels carry over, and Yes/No labels on decision branches get the yes/no colors.
  • Loose nodes are laid out first, then each frame below them (or beside them for top-down flows).
  • The result reports node, edge and frame counts plus any lines it skipped (styles, classes and links to a subgraph are ignored). Only flowcharts are supported.

Then check it with lint_diagram and render_diagram as usual.

Lanes and notes

Frames give each flow a visible, titled lane (and export as Mermaid subgraphs):

  1. add_node a group per flow with its title as label and a position (stack lanes vertically; leave 200+ px between them).
  2. add_node the flow's steps with groupId set to the group's ref. Positions can be omitted.
  3. {"op": "auto_layout", "node_ids": ["<group ref>"]} lays the members out inside that frame (below its 36 px title bar, 24 px padding) and grows the frame to fit. Or place them yourself and finish with {"op": "fit_group", "id": "<group ref>"}.
  4. Moving a group (update_node position) moves its members with it. Deleting a group keeps its members, ungrouped. Groups don't nest and can't be connected.

note nodes are free text for context (they auto-size like actions, up to 240 px wide); they are never connected and the flow checks ignore them.

Working alongside people

  1. Read the diagram and note its version.
  2. Send your batch with expected_version set to it.
  3. If someone saved in between, nothing is written and the tool returns an error with error: "version_conflict", current_version, and changes: nodes added, removed, moved, relabeled; edges added, removed, rewired, rerouted. Re-read only what you need, adjust the plan, and retry with the new version.
  4. Without expected_version, your batch applies on top of whatever is saved; a save that lands mid-write is never overwritten (the batch re-applies after it).

Open editor tabs show your edits live with an "Updated by ... via MCP" notice, and the editor never silently overwrites them.

Checking your work

  • lint_diagram: overlapping nodes, edges drawn through other nodes, decisions with missing, unlabeled or same-side branches, unreachable, orphan or dead-end nodes, edges without stored handles. Each issue names the ids and a fix. clean: true means no errors or warnings.
  • render_diagram: a PNG drawn exactly as the canvas draws it. Crop with node_ids (one flow at a time reads best) or bbox.

Reading the response

  • Version token: the version (or updated_at) value. Opaque; compare it for equality only.
  • Sizes: decision 130x130 is exact. Auto-sized nodes (no stored width/height) report an estimate, marked "~" in full format and "estimated": true in compact.
  • Handles: a stored handle is reported as-is. Older edges with no stored handle report the handle the canvas computes from node positions, marked "auto"; it changes if the nodes move. Writing that edge's handles with update_edge pins them.

Prompts

Ready-made starting points the person can pick in clients that show MCP prompts (in Claude Code, /mcp__product-pillars__<name>):

  • draw_flowchart (flow, project): Draw a new flowchart from a plain-language description, then share the link to open it.
  • diagram_from_source (source, focus): Read a spec, doc or part of a codebase and draw the flows it describes.
  • review_diagram (diagram): Check a diagram for layout and logic problems and suggest fixes before changing anything.

Tools

list_diagrams

List the diagrams you can access, newest first. Each has id, name, status, updated_at (also its version token), your role (owner and editor can write), project {id, name} or null, node_count and edge_count.

Parameters (JSON Schema):

{"type":"object","properties":{},"additionalProperties":false}

list_projects

List the projects you own or are a member of: id, name, your role, diagram_count. Pass a project id to create_diagram (project_id) to create a diagram inside it.

Parameters (JSON Schema):

{"type":"object","properties":{},"additionalProperties":false}

get_diagram

Read one diagram. Every format starts with its id and version token.

  • full (default): Markdown with a Mermaid block, "## Nodes" (id, label, type, position, size) and "## Edges" (id, labels, source and target node ids with their handles, label, variant).
  • compact: JSON, one node or edge per line, no descriptions. Nodes: id, type, label, x, y, w, h ("estimated": true when the node auto-sizes to its label). Edges: id, source, sourceHandle, target, targetHandle, label, variant, direction ("auto": true when a handle is computed from positions instead of stored). Use this for large diagrams.
  • mermaid: only the Mermaid source.

Positions are top-left corners in px. Ids are what edit_diagram ops take.

Parameters (JSON Schema):

{"type":"object","properties":{"idOrName":{"type":"string","description":"Diagram id (or the exact name of a diagram you own)."},"format":{"description":"full (default), compact, or mermaid.","type":"string","enum":["full","compact","mermaid"]}},"required":["idOrName"],"additionalProperties":false}

create_diagram

Create a diagram and return its id, name and version. Empty by default: then add everything with one edit_diagram batch. Or pass mermaid (a Mermaid flowchart, or Markdown containing one) to start from it: shapes become node types ({decision}, ([start/end]), [[system step]], [user step]), subgraphs become frames, Yes/No branch labels get colored, and everything is laid out for you; the result reports counts and any lines it skipped. Use list_projects to find a project_id.

Parameters (JSON Schema):

{"type":"object","properties":{"name":{"type":"string"},"project_id":{"description":"Create inside this project (from list_projects).","anyOf":[{"type":"string"},{"type":"null"}]},"mermaid":{"description":"Mermaid flowchart source (flowchart or graph) to draw, or Markdown containing a mermaid block.","type":"string"}},"additionalProperties":false}

edit_diagram

Apply a batch of ops to a diagram's nodes and edges, in order. Atomic: if any op is invalid nothing is saved and the error names the op index. Ops: add_node, update_node, delete_node, add_edge, update_edge, delete_edge, plus layout ops: auto_layout (layered layout, LR or TB, of all or some nodes; re-routes their edges), align, distribute, fit_group (wrap a frame around its members). An add_node "ref" can stand in for the new node's id in later ops of the same batch. Handles are top | right | bottom | left; omitted ones are chosen from the final node positions and saved (see the server instructions). width/height only apply to userAction and systemAction. Pass expected_version to refuse the batch if the diagram changed since you read it. Returns a summary: refs (ref to new id), ids created without a ref, op counts, defaulted handles, positions of nodes layout ops moved, warnings, totals and the new version. return "full" adds the whole diagram as Markdown. Example, a left-to-right flow with a decision (row aligned by center; the "No" branch drops 150 px):

[
  {"op":"add_node","ref":"start","node":{"type":"start","label":"Start","position":{"x":0,"y":43}}},
  {"op":"add_node","ref":"check","node":{"type":"decision","label":"Valid?","position":{"x":300,"y":0}}},
  {"op":"add_node","ref":"save","node":{"type":"systemAction","label":"Save record","position":{"x":600,"y":43}}},
  {"op":"add_node","ref":"fix","node":{"type":"userAction","label":"Fix input","position":{"x":600,"y":193}}},
  {"op":"add_edge","edge":{"source":"start","target":"check","sourceHandle":"right","targetHandle":"left"}},
  {"op":"add_edge","edge":{"source":"check","target":"save","sourceHandle":"right","targetHandle":"left","label":"Yes","variant":"yes"}},
  {"op":"add_edge","edge":{"source":"check","target":"fix","sourceHandle":"bottom","targetHandle":"left","label":"No","variant":"no"}}
]

Parameters (JSON Schema):

{"type":"object","properties":{"id":{"type":"string","description":"Diagram id (or the exact name of a diagram you own)."},"ops":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"op":{"type":"string","const":"add_node"},"ref":{"type":"string","description":"Any string. Later ops in the same batch can use it in place of the new id (edge endpoints, update_*, delete_*)."},"node":{"type":"object","properties":{"type":{"type":"string","enum":["userAction","systemAction","decision","start","end","group","note"],"description":"start/end: where a flow begins/ends. userAction: a person does something. systemAction: the system does something. decision: a question with labeled branches. group: a titled frame (lane or section) that other nodes join via groupId; label is its title. note: free text, not part of the flow. group and note nodes have no handles and cannot be connected."},"label":{"type":"string"},"description":{"description":"Free-form context; travels with the diagram, not drawn on the canvas.","type":"string"},"position":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"description":"Top-left corner of the node in canvas px (x right, y down)."},"width":{"type":"number","description":"Fixed width in px. Honored on userAction, systemAction and note (min 120 for actions), and on group (default 640)."},"height":{"type":"number","description":"Fixed height in px. Honored on userAction, systemAction and note (min 48 for actions), and on group (default 280)."},"groupId":{"type":"string","description":"A group node (id or ref) for this node to belong to. Groups do not nest."}},"required":["type"],"additionalProperties":false}},"required":["op","node"],"additionalProperties":false},{"type":"object","properties":{"op":{"type":"string","const":"update_node"},"id":{"type":"string","description":"Node id (or a ref from this batch)."},"patch":{"type":"object","properties":{"type":{"type":"string","enum":["userAction","systemAction","decision","start","end","group","note"],"description":"start/end: where a flow begins/ends. userAction: a person does something. systemAction: the system does something. decision: a question with labeled branches. group: a titled frame (lane or section) that other nodes join via groupId; label is its title. note: free text, not part of the flow. group and note nodes have no handles and cannot be connected."},"label":{"type":"string"},"description":{"type":"string"},"position":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"description":"Top-left corner of the node in canvas px (x right, y down)."},"width":{"type":"number","description":"Fixed width in px. Honored on userAction, systemAction and note (min 120 for actions), and on group (default 640)."},"height":{"type":"number","description":"Fixed height in px. Honored on userAction, systemAction and note (min 48 for actions), and on group (default 280)."},"groupId":{"description":"Join this group (id or ref), or null to leave its group.","anyOf":[{"type":"string","description":"A group node (id or ref) for this node to belong to. Groups do not nest."},{"type":"null"}]}},"additionalProperties":false},"move_members":{"description":"When moving a group: also move its members by the same amount (default true).","type":"boolean"}},"required":["op","id","patch"],"additionalProperties":false},{"type":"object","properties":{"op":{"type":"string","const":"delete_node"},"id":{"type":"string","description":"Node id. Its edges are deleted too."}},"required":["op","id"],"additionalProperties":false},{"type":"object","properties":{"op":{"type":"string","const":"add_edge"},"ref":{"type":"string","description":"Any string. Later ops in the same batch can use it in place of the new id (edge endpoints, update_*, delete_*)."},"edge":{"type":"object","properties":{"source":{"type":"string","description":"Node id, or a ref from an add_node earlier in this batch."},"target":{"type":"string","description":"Node id, or a ref from an add_node earlier in this batch."},"sourceHandle":{"type":"string","enum":["top","right","bottom","left"],"description":"Which side of the node the edge attaches to: top | right | bottom | left. Omit to have it chosen from node positions (right -> left for a step right, bottom -> top for a step down, bottom/top -> left for a decision branch leaving its row, bottom -> bottom for a loop back left)."},"targetHandle":{"type":"string","enum":["top","right","bottom","left"],"description":"Which side of the node the edge attaches to: top | right | bottom | left. Omit to have it chosen from node positions (right -> left for a step right, bottom -> top for a step down, bottom/top -> left for a decision branch leaving its row, bottom -> bottom for a loop back left)."},"label":{"type":"string"},"direction":{"type":"string","enum":["none","forward","reverse","both"],"description":"Arrowheads. Default forward (source -> target)."},"variant":{"type":"string","enum":["default","yes","no"],"description":"Color for decision branches: yes (blue) or no (red). Default: plain."}},"required":["source","target"],"additionalProperties":false}},"required":["op","edge"],"additionalProperties":false},{"type":"object","properties":{"op":{"type":"string","const":"update_edge"},"id":{"type":"string","description":"Edge id (or a ref from this batch)."},"patch":{"type":"object","properties":{"source":{"type":"string"},"target":{"type":"string"},"sourceHandle":{"type":"string","enum":["top","right","bottom","left"],"description":"Which side of the node the edge attaches to: top | right | bottom | left. Omit to have it chosen from node positions (right -> left for a step right, bottom -> top for a step down, bottom/top -> left for a decision branch leaving its row, bottom -> bottom for a loop back left)."},"targetHandle":{"type":"string","enum":["top","right","bottom","left"],"description":"Which side of the node the edge attaches to: top | right | bottom | left. Omit to have it chosen from node positions (right -> left for a step right, bottom -> top for a step down, bottom/top -> left for a decision branch leaving its row, bottom -> bottom for a loop back left)."},"label":{"type":"string"},"direction":{"type":"string","enum":["none","forward","reverse","both"],"description":"Arrowheads. Default forward (source -> target)."},"variant":{"type":"string","enum":["default","yes","no"],"description":"Color for decision branches: yes (blue) or no (red). Default: plain."}},"additionalProperties":false}},"required":["op","id","patch"],"additionalProperties":false},{"type":"object","properties":{"op":{"type":"string","const":"delete_edge"},"id":{"type":"string","description":"Edge id."}},"required":["op","id"],"additionalProperties":false},{"type":"object","properties":{"op":{"type":"string","const":"auto_layout"},"direction":{"description":"LR (default): flows left to right. TB: top to bottom.","type":"string","enum":["LR","TB"]},"node_ids":{"description":"Lay out only these nodes (ids or refs), keeping their top-left corner in place. A group id stands for its members: they are laid out inside that frame and the frame grows to fit. Default: every node except frames.","type":"array","items":{"type":"string"}},"node_gap":{"description":"Gap between nodes in the same column/row. Default 60.","type":"number"},"rank_gap":{"description":"Gap between consecutive columns/rows. Default 100.","type":"number"},"keep_handles":{"description":"Keep stored handles on edges touching moved nodes. Default false: they are re-routed from the new positions.","type":"boolean"}},"required":["op"],"additionalProperties":false},{"type":"object","properties":{"op":{"type":"string","const":"align"},"node_ids":{"type":"array","items":{"type":"string"},"description":"At least 2 node ids or refs."},"to":{"type":"string","enum":["left","center","right","top","middle","bottom"],"description":"left/center/right line up x; top/middle/bottom line up y. middle aligns vertical centers."},"anchor":{"description":"Align to this node (one of node_ids) instead of the group's bounding box.","type":"string"}},"required":["op","node_ids","to"],"additionalProperties":false},{"type":"object","properties":{"op":{"type":"string","const":"fit_group"},"id":{"type":"string","description":"The group node (id or ref) to wrap around its members."},"padding":{"description":"Space between the frame and its members, px. Default 24 (plus the 36 px title bar on top).","type":"number"}},"required":["op","id"],"additionalProperties":false},{"type":"object","properties":{"op":{"type":"string","const":"distribute"},"node_ids":{"type":"array","items":{"type":"string"},"description":"Node ids or refs, spaced in their current order (3+, or 2+ with gap)."},"axis":{"type":"string","enum":["horizontal","vertical"]},"gap":{"description":"Exact px between neighbors, starting from the first node. Default: equal gaps between the first and last.","type":"number"}},"required":["op","node_ids","axis"],"additionalProperties":false}]}},"expected_version":{"description":"The version you planned against (from your last read). If the diagram changed since, nothing is saved and you get a summary of what changed.","type":"string"},"return":{"description":"summary (default): ids, counts, warnings, version. full: also the whole diagram as Markdown.","type":"string","enum":["summary","full"]}},"required":["id","ops"],"additionalProperties":false}

lint_diagram

Check a diagram for problems without looking at it. Returns clean (no errors or warnings), counts by severity, and issues, each with the rule, the node/edge ids involved and a suggested fix. Rules: dangling_edge, dangling_group, overlap, group_overlap, outside_group, edge_crosses_node, auto_handles, decision_branches, decision_unlabeled_branch, decision_shared_handle, no_start, unreachable, orphan, dead_end. Errors: dangling edges, overlapping nodes. Warnings: edges drawn through other nodes, decisions with fewer than two branches, unlabeled branches or two branches on one side, a missing start node, unreachable, orphan or dead-end nodes. Info: edges with no stored handles. Run it after a batch; it uses the same geometry as the canvas.

Parameters (JSON Schema):

{"type":"object","properties":{"id":{"type":"string","description":"Diagram id (or the exact name of a diagram you own)."},"rules":{"description":"Only run these rules (default: all).","type":"array","items":{"type":"string","enum":["dangling_edge","dangling_group","overlap","group_overlap","outside_group","edge_crosses_node","auto_handles","decision_branches","decision_unlabeled_branch","decision_shared_handle","no_start","unreachable","orphan","dead_end"]}}},"required":["id"],"additionalProperties":false}

render_diagram

See the diagram without a browser: an image drawn exactly as the canvas draws it (same shapes, sizes, label wrapping, edge routing and handles). Returns a PNG (default) or SVG, plus the canvas region shown. Large diagrams are scaled down to max_dimension, so to read details crop with node_ids (e.g. one flow) or bbox. Pair it with lint_diagram after each batch.

Parameters (JSON Schema):

{"type":"object","properties":{"id":{"type":"string","description":"Diagram id (or the exact name of a diagram you own)."},"format":{"description":"png (default): an image. svg: the SVG source as text.","type":"string","enum":["png","svg"]},"node_ids":{"description":"Crop to these nodes plus padding (anything else inside the frame still draws).","type":"array","items":{"type":"string"}},"bbox":{"description":"Crop to this canvas region in px. Wins over node_ids.","type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"}},"required":["x","y","width","height"],"additionalProperties":false},"padding":{"description":"Space around the cropped content, px. Default 40.","type":"number"},"scale":{"description":"Canvas px to image px. Default 1, max 2.","type":"number"},"max_dimension":{"description":"Longest side of the image, px. Default 2000, max 4000.","type":"number"}},"required":["id"],"additionalProperties":false}

update_diagram

Change a diagram's name, status, description, project or Mermaid direction. Owners and editors can rename and change status; only the owner can move it to another project (or out of one with project_id null). Returns the id, name, status, project_id, direction and new version. Nodes and edges are changed with edit_diagram, not here.

Parameters (JSON Schema):

{"type":"object","properties":{"id":{"type":"string","description":"Diagram id (or the exact name of a diagram you own)."},"name":{"type":"string"},"status":{"description":"draft, active or archived.","type":"string","enum":["draft","active","archived"]},"description":{"description":"Diagram-level summary. null clears it.","anyOf":[{"type":"string"},{"type":"null"}]},"project_id":{"description":"Move into this project (from list_projects), or null for none.","anyOf":[{"type":"string"},{"type":"null"}]},"direction":{"description":"Mermaid export direction: LR (left to right), TD (top down), or auto (inferred from the canvas, the default).","type":"string","enum":["LR","TD","auto"]}},"required":["id"],"additionalProperties":false}

share_diagram

Get, create or revoke the diagram's public read-only link (owner only). action "get" (default) returns the active link or status "none"; "create" returns the active link, minting one only if none exists; "revoke" disables every link. A link gives url (rendered diagram for people) and markdown_url (raw Markdown for agents). Anyone with the link can view; it never grants edit access.

Parameters (JSON Schema):

{"type":"object","properties":{"id":{"type":"string","description":"Diagram id (or the exact name of a diagram you own)."},"action":{"description":"get (default), create, or revoke.","type":"string","enum":["get","create","revoke"]}},"required":["id"],"additionalProperties":false}