Skip to main content
Glama

DrawFather

Hand-drawn visuals for AI agents.

drawfather.com

Launch roadmap · Contributing · Licensing

Launch verification is in progress. See Phase 8 evidence and remaining gates, local client setup, and container setup. No npm release or MCP registry listing is published yet.

Agents can start with get_capabilities or the DrawFather skill. Routine tool replies contain compact metadata; source, images, and inline exports are explicit options. See the agent API.

Mascot concept: AI-generated brand artwork. The example diagram below is rendered by DrawFather from editable JSON.

DrawFather is a source-available MCP server that creates sketch-style drawings from editable JSON. Your AI assistant calls the tools; DrawFather saves a .drawfather file and exports SVG, PNG, JPG, WebP, or vector PDF. No drawing interface, account, API key, or model download is required.

The engine uses Elastic License 2.0, a fair-code license. The .drawfather JSON schema and examples use MIT so the file format can be implemented independently. Read LICENSING.md for permitted use, hosted-service restrictions, and drawing output rights.

Describe it. DrawFather composes it.

Give your agent the steps or the connections. DrawFather measures the lettering, sizes the shapes, saves editable .drawfather source, and returns a compact result. Request preview: true for a PNG or includeSource: true for the complete source in the response.

{
  "name": "product-launch",
  "design": {
    "template": "process",
    "title": "From signup to first value",
    "steps": ["Sign up", "Verify email", "Create workspace", "First useful action"]
  }
}

Call compose_drawing with this input:

A process automatically composed and rendered by DrawFather

Three general composition templates are included: process for 2–24 ordered steps, cycle for 3–12 steps with curved connections, and architecture for up to 48 nodes and 96 connections. Process and architecture accept direction: "auto", "horizontal", or "vertical". Labels, optional details, and node shapes determine the required space. Auto process flows wrap after four steps per row; larger architectures default to vertical.

Each named step can be a string or an object with id, label, optional detail, and shape (rectangle, ellipse, or diamond). Architecture uses these node objects plus connections with from, to, and an optional label. Supply explicit IDs when you want to edit particular elements later; df- is reserved for generated elements. All templates accept an optional title, subtitle, and deterministic seed.

Use list_templates to discover complete inputs, or inspect the MIT-licensed composition schema. New compositions use native v2: the file retains its creation request, current semantic model, resolved elements, and constrained view. Reopen the file and use edit_drawing with reflow to regenerate the current model without supplying another request.

Use edit_drawing for semantic changes, pins, groups, and constraints; update_drawing supports complete-element geometry edits. To generate a new layout in an existing file, call compose_drawing with its current expectedRevision and a complete design. Explicit composition replacement replaces its content; existing pins and surviving layout constraints remain protected. Omit expectedRevision to create a new drawing without overwriting an existing file.

Related MCP server: tldraw MCP Server

Ten technical diagram families

Use compose_technical for flowcharts, sequence diagrams, C4 architecture, ER models, state machines, class/domain models, data flows, dependency graphs, swimlane activities, and deployment/network diagrams. Typed notation retains fields, keys, cardinalities, guards, message order, ownership and boundaries in editable JSON. Shared named views, hand-drawn symbols, callouts, legends and layers support focused explanations.

Discover get_capabilities with topic: "technical", then recipe: "oauth", "ci-cd", "microservices", "event-driven", "kubernetes", "rag" or another catalog ID for a complete example. Read the technical contract and browse twenty generated examples with before/after source, images and edit code. Import Mermaid flowchart, sequence and ER code, then hand off editable Excalidraw or draw.io scenes. See the conversion examples with images and code and support/fidelity matrix.

Eight creative diagram families

Use compose_creative for mind maps, Gantt schedules, timelines, user journeys, Kanban boards, annotated screenshots, storyboards and wireframes. Revise typed items with edit_creative: expand a branch, change a date, move the same card, or update a panel caption. Saved drawings double as reusable templates through reuseFrom, with component libraries and shared brand presets.

One reusable character in three hand-drawn storyboard panels

Browse the creative gallery for images, editable source and before/after edit code. The creative contract covers portable embedded images/SVG assets, local fonts and explicit glyph fallback, rotation/layers, accessible summaries, selectable SVG/PDF text and vector PDF page controls. Phase 7 evidence records local verification and remaining launch boundaries.

Revise a diagram while preserving its layout

Add a cache, rename the API, and remove an obsolete dependency through one revision-checked edit. Unaffected shapes and annotations keep their geometry; pinned elements keep their exact positions.

An architecture after a semantic edit

Before image · Before source · Edited source · Complete edit batch

Save the before source as system with create_drawing, then call edit_drawing:

{
  "name": "system",
  "expectedRevision": 1,
  "operations": [
    {
      "op": "insert_between",
      "connectionId": "df-edge-2",
      "node": { "id": "redis", "label": "Redis", "role": "database" },
      "secondConnectionId": "redis-db"
    },
    { "op": "rename", "id": "api", "label": "Core API" },
    { "op": "disconnect", "id": "df-edge-4" }
  ]
}

Use group and regroup for nested containers; pin and unpin for fixed origins; and constraint for relative placement or alignment. Changed shapes grow to fit their labels, affected connections are rerouted, and conflicting constraints return an actionable error without saving a partial edit. Use reflow to lay out selected nodes or the entire current model. See the operation reference.

drawing_history lists local snapshots and migration backups. Its undo, redo, and restore actions require the current revision, create a new revision, and survive server restarts. Existing v1 drawings remain readable and renderable; migrate_drawing or the first successful semantic edit creates a byte-for-byte backup before upgrading them. See migration and recovery.

Inspect and preview repairs

Call check_drawing to find overlaps, clipped strokes, small or overflowing text, blocked connectors, group-boundary problems, poor contrast, and readability issues at intended output dimensions. Findings include severity, affected IDs, and suggested corrections.

Call repair_drawing with action: "preview" and the current expectedRevision. It proposes bounded spacing, label growth, rerouting, container fitting, and canvas fitting without changing files. Request preview: true and includeSource: true when reviewing the proposed image and source, then apply the returned planId with the same revision and repair/check options. Application is one undoable revision. Pins, constraints, annotations, seeds, and explicitly permitted overlaps are preserved; unresolved errors block the write.

Blocked connectors after visual repair

Before image · Editable source · Before/after reports · Visual checking and repair reference

For intended layering, use allow_overlap with an ids pair in edit_drawing, or supply checks.allowOverlaps during inspection and repair. Checking output dimensions is separate from export options.scale, which controls actual delivery size.

Read and patch only what changed

Read one element with get_drawing using view: "elements", ids: ["api"]. Then patch its label or partial style without sending its coordinates again:

{
  "name": "system",
  "expectedRevision": 1,
  "patches": [{ "id": "api", "label": "Core API", "style": { "fill": "#d3e1f5" } }]
}

Call patch_drawing with this input. Results report changed IDs, revision, diagnostic counts/findings, and source paths. get_drawing defaults to a summary; view: "graph" pages semantic relationships and view: "source" retrieves the complete editable document. Selected reads, lists, diagnostics, and history use cursors tied to the current source and query.

Use preview_drawing for a PNG with explicit size, crop or selected IDs, padding and background. Exports return their local paths by default; inline: true embeds SVG text or a raster preview. These controls preserve the source and full-resolution export. See the API contract, agent skill, and seven-call reference task.

Maintain drawings with the repository

A project manifest links native sources, stable images, export settings and documentation. project_diagrams exposes the same check/render/affected/diff workflow through MCP; the CLI supports batch builds and CI:

drawfather validate --manifest drawfather.project.json
drawfather render --manifest drawfather.project.json --write-docs
drawfather check --manifest drawfather.project.json
drawfather affected --manifest drawfather.project.json --base origin/main
drawfather diff --manifest drawfather.project.json --id system --base origin/main

Stable filenames keep Markdown embeds intact; optional revision copies retain earlier source revisions. Results include relative Markdown links, alt text, captions, dimensions and editable-source backlinks. Generated blocks preserve surrounding prose; existing gallery-style embeds can be checked without being rewritten.

Code paths, symbols and supplied commit IDs are recorded in the manifest. Missing/stale images and documentation are separate from source relationships that need review. Rendering never clears required code review. After inspecting the relationships, acknowledge the exact source/reference hashes returned by the check. A fresh image or acknowledgement alone cannot establish architectural accuracy.

Exports support source, light, dark, paper and transparent backgrounds, scale settings, and explicit source/reference metadata. Metadata defaults to none; enabling it discloses the declared references or full native JSON in SVG/XMP. The source stays unchanged.

See the runnable repository example, README/architecture/onboarding/ADR examples, GitHub Actions recipe, and project contract. npm run docs:check verifies this repository's gallery and managed example against their committed receipts.

Choose the sketch character

sketch controls how hand-drawn the strokes feel. roundness controls rectangle corners separately:

Sketch level

Appearance

tidy

Restrained stroke variation and straighter edges

handwritten

Gently bowed edges, uneven corners, and visible pencil-like strokes

loose

Stronger wobble, curvature, and overlapping strokes

{
  "template": "process",
  "title": "Try, learn, repeat",
  "sketch": "handwritten",
  "roundness": 0.35,
  "seed": 42,
  "steps": ["Build", "Measure", "Learn"]
}

Pass this as design to compose_drawing. New compositions default to sketch: "handwritten" and roundness: 0.25. Roundness ranges from 0 (square) to 1 (fully rounded), expressed as a fraction of half the shorter side. Each node can override sketch or roundness; roundness applies to rectangular nodes.

In native .drawfather source, set sketch at the document level or override it on individual elements. Set roundness on a rectangle. Native documents without a sketch preset keep the original v1 stroke style; rectangles without roundness keep square corners. Change a saved drawing's preset with update_drawing, supplying its expectedRevision and sketch; sketch: null restores the original style. To change corner rounding, upsert the complete rectangle element.

Randomness is seeded, so the same source produces the same strokes. Editing a label or another element keeps the shape's contour stable. Change the document seed for a fresh variation; explicit element seeds pin individual strokes. Updating the seed preserves positions, while recomposing an architecture may also change layout tie-breaks. Presets affect shape and connector strokes; lettering keeps the readable Kalam font.

For fine tuning, element roughness remains in the range 0.5–3. With a preset, 1.2 is neutral: the effective stroke roughness is the preset's value multiplied by roughness / 1.2. Higher values add stroke variation. Rectangle edge curvature also comes from a seeded contour; changing corner roundness is independent of the preset.

See the rendered comparison and editable source in the gallery below.

Every image below is rendered by DrawFather from the accompanying .drawfather JSON. Expand a code block to copy the full source, or download the source file and adapt it. All example sources and images are MIT licensed.

Regenerate every example image and this gallery with npm run example. PNG, JPG, and WebP versions are also generated in output/.

Inspect and repair blocked connectors

Visual inspection finds two connectors crossing Storage. A bounded repair reroutes those connections while preserving every node, annotation, ID, and seed.

Inspect and repair blocked connectors, rendered by DrawFather

Try asking your agent: Check the diagram for visual defects, preview repairs, then apply the reviewed plan using its revision and plan ID.

Editable source · SVG image

{
  "type": "drawfather",
  "revision": 0,
  "title": "Dense branches",
  "seed": 42,
  "sketch": "handwritten",
  "canvas": {
    "width": 1100,
    "height": 760,
    "background": "#ffffff"
  },
  "version": 1,
  "elements": [
    {
      "id": "api",
      "x": 90,
      "y": 260,
      "width": 180,
      "height": 100,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "API",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "web",
      "x": 760,
      "y": 100,
      "width": 180,
      "height": 100,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Web",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "jobs",
      "x": 760,
      "y": 330,
      "width": 180,
      "height": 100,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Jobs",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "events",
      "x": 760,
      "y": 560,
      "width": 180,
      "height": 100,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Events",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "blocker",
      "x": 410,
      "y": 240,
      "width": 180,
      "height": 100,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Storage",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "note",
      "x": 90,
      "y": 560,
      "width": 260,
      "height": 70,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Keep the annotations",
      "fontSize": 24,
      "type": "text",
      "align": "left"
    },
    {
      "id": "api-web",
      "type": "arrow",
      "from": {
        "elementId": "api",
        "anchor": "right"
      },
      "to": {
        "elementId": "web",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "waypoints": [
        [
          311.2,
          310
        ],
        [
          311.2,
          150
        ],
        [
          718.8,
          150
        ]
      ],
      "text": "",
      "fontSize": 24
    },
    {
      "id": "api-jobs",
      "type": "arrow",
      "from": {
        "elementId": "api",
        "anchor": "right"
      },
      "to": {
        "elementId": "jobs",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "waypoints": [
        [
          311.2,
          310
        ],
        [
          311.2,
          380
        ],
        [
          718.8,
          380
        ]
      ],
      "text": "",
      "fontSize": 24
    },
    {
      "id": "api-events",
      "type": "arrow",
      "from": {
        "elementId": "api",
        "anchor": "right"
      },
      "to": {
        "elementId": "events",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    }
  ]
}

Before image · Before source · Inspection reports

An architecture edited without a redraw

Insert Redis, rename the API, remove a legacy dependency, and create a nested cache group. The API and database stay pinned, and the client, worker, and heading retain their existing geometry.

An architecture edited without a redraw, rendered by DrawFather

Try asking your agent: Add Redis between the API and database, rename the API, remove the legacy dependency, and keep the rest in place.

Editable source · SVG image

{
  "type": "drawfather",
  "revision": 0,
  "title": "An architecture that can evolve",
  "seed": 42,
  "sketch": "handwritten",
  "canvas": {
    "width": 1680,
    "height": 640,
    "background": "#fffdf7"
  },
  "version": 2,
  "elements": [
    {
      "id": "df-title",
      "x": 64,
      "y": 64,
      "width": 1552,
      "height": 73,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "An architecture that can evolve",
      "fontSize": 36,
      "type": "text",
      "align": "left"
    },
    {
      "id": "client",
      "x": 88,
      "y": 207,
      "width": 271,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#ffe3a0",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Client",
      "fontSize": 24,
      "type": "ellipse"
    },
    {
      "id": "api",
      "x": 573,
      "y": 207,
      "width": 184,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#d3e1f5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Core API",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "db",
      "x": 1408,
      "y": 207,
      "width": 184,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#c6e6d5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Database",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "worker",
      "x": 977,
      "y": 207,
      "width": 184,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#f5c8b6",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Worker",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "df-edge-1",
      "type": "arrow",
      "from": {
        "elementId": "client",
        "anchor": "right"
      },
      "to": {
        "elementId": "api",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "df-label-1",
      "x": 423,
      "y": 258,
      "width": 86,
      "height": 47,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "request",
      "fontSize": 18,
      "type": "text",
      "align": "center"
    },
    {
      "id": "df-edge-2",
      "type": "arrow",
      "from": {
        "elementId": "api",
        "anchor": "right"
      },
      "to": {
        "elementId": "redis",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "waypoints": [
        [
          783,
          255
        ],
        [
          783,
          494.9
        ],
        [
          1212.5,
          494.9
        ]
      ],
      "text": "",
      "fontSize": 24
    },
    {
      "id": "df-label-2",
      "x": 961.75,
      "y": 435.9,
      "width": 72,
      "height": 47,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "query",
      "fontSize": 18,
      "type": "text",
      "align": "center"
    },
    {
      "id": "df-edge-3",
      "type": "arrow",
      "from": {
        "elementId": "api",
        "anchor": "right"
      },
      "to": {
        "elementId": "worker",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "df-label-3",
      "x": 821,
      "y": 205,
      "width": 92,
      "height": 47,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "enqueue",
      "fontSize": 18,
      "type": "text",
      "align": "center"
    },
    {
      "id": "backend",
      "x": 541,
      "y": 125.1,
      "width": 1083,
      "height": 482,
      "stroke": "#6b7280",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Backend services",
      "fontSize": 22,
      "type": "container",
      "padding": 32
    },
    {
      "id": "redis",
      "x": 1238.5,
      "y": 446.9,
      "width": 184,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#e2d4ef",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Redis",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "redis-db",
      "type": "arrow",
      "from": {
        "elementId": "redis",
        "anchor": "top"
      },
      "to": {
        "elementId": "db",
        "anchor": "bottom"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "waypoints": [
        [
          1330.5,
          420.9
        ],
        [
          1500,
          420.9
        ],
        [
          1500,
          329
        ]
      ],
      "text": "",
      "fontSize": 24
    },
    {
      "id": "cache",
      "x": 1206.5,
      "y": 367,
      "width": 248,
      "height": 208,
      "stroke": "#6b7280",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Cache",
      "fontSize": 22,
      "type": "container",
      "padding": 32
    }
  ],
  "model": {
    "kind": "architecture",
    "direction": "auto",
    "origin": {
      "source": "composition",
      "composition": {
        "title": "An architecture that can evolve",
        "seed": 42,
        "sketch": "handwritten",
        "roundness": 0.25,
        "template": "architecture",
        "direction": "auto",
        "nodes": [
          {
            "id": "client",
            "label": "Client",
            "shape": "ellipse",
            "role": "person"
          },
          {
            "id": "api",
            "label": "API",
            "shape": "rectangle",
            "role": "service"
          },
          {
            "id": "db",
            "label": "Database",
            "shape": "rectangle",
            "role": "database"
          },
          {
            "id": "worker",
            "label": "Worker",
            "shape": "rectangle",
            "role": "service"
          }
        ],
        "connections": [
          {
            "from": "client",
            "to": "api",
            "label": "request"
          },
          {
            "from": "api",
            "to": "db",
            "label": "query"
          },
          {
            "from": "api",
            "to": "worker",
            "label": "enqueue"
          },
          {
            "from": "worker",
            "to": "db",
            "label": "legacy path"
          }
        ]
      }
    },
    "nodes": [
      {
        "id": "client",
        "label": "Client",
        "shape": "ellipse",
        "role": "person"
      },
      {
        "id": "api",
        "label": "Core API",
        "shape": "rectangle",
        "role": "service",
        "parentId": "backend"
      },
      {
        "id": "redis",
        "label": "Redis",
        "shape": "rectangle",
        "role": "database",
        "parentId": "cache"
      },
      {
        "id": "db",
        "label": "Database",
        "shape": "rectangle",
        "role": "database",
        "parentId": "backend"
      },
      {
        "id": "worker",
        "label": "Worker",
        "shape": "rectangle",
        "role": "service",
        "parentId": "backend"
      }
    ],
    "connections": [
      {
        "id": "df-edge-1",
        "from": "client",
        "to": "api",
        "role": "relationship",
        "label": "request",
        "labelId": "df-label-1"
      },
      {
        "id": "df-edge-2",
        "from": "api",
        "to": "redis",
        "role": "relationship",
        "label": "query",
        "labelId": "df-label-2"
      },
      {
        "id": "df-edge-3",
        "from": "api",
        "to": "worker",
        "role": "relationship",
        "label": "enqueue",
        "labelId": "df-label-3"
      },
      {
        "id": "redis-db",
        "from": "redis",
        "to": "db",
        "role": "relationship"
      }
    ],
    "groups": [
      {
        "id": "backend",
        "label": "Backend services",
        "padding": 32
      },
      {
        "id": "cache",
        "label": "Cache",
        "parentId": "backend",
        "padding": 32
      }
    ],
    "annotations": [
      {
        "id": "df-title"
      }
    ]
  },
  "view": {
    "id": "main",
    "pins": [
      {
        "id": "api",
        "x": 573,
        "y": 207
      },
      {
        "id": "db",
        "x": 1408,
        "y": 207
      }
    ],
    "constraints": [],
    "intentionalOverlaps": []
  }
}

Before image · Before source · Atomic edit batch

Choose your sketch character

Compare tidy, handwritten, and loose strokes with square, soft, and round corners. The first three rows use seed 42; the last row shows different seeds with the same handwritten style. Randomness is reproducible, and style can be chosen per drawing or per element.

Choose your sketch character, rendered by DrawFather

Try asking your agent: Draw a comparison of all three sketch levels with square and rounded boxes.

Editable source · SVG image

{
  "type": "drawfather",
  "revision": 0,
  "title": "Sketch levels and rounded boxes",
  "seed": 42,
  "canvas": {
    "width": 1150,
    "height": 950,
    "background": "#fffdf7"
  },
  "version": 1,
  "elements": [
    {
      "id": "title",
      "x": 48,
      "y": 25,
      "width": 1050,
      "height": 70,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "How hand-drawn should it feel?",
      "fontSize": 36,
      "type": "text",
      "align": "left"
    },
    {
      "id": "subtitle",
      "x": 48,
      "y": 95,
      "width": 1050,
      "height": 60,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Three sketch levels. Three corner styles. Always reproducible.",
      "fontSize": 20,
      "type": "text",
      "align": "left"
    },
    {
      "id": "label-tidy",
      "x": 42,
      "y": 185,
      "width": 190,
      "height": 130,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Tidy",
      "fontSize": 25,
      "type": "text",
      "align": "left"
    },
    {
      "id": "tidy-0",
      "x": 250,
      "y": 185,
      "width": 240,
      "height": 130,
      "sketch": "tidy",
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#ffe3a0",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "seed": 42,
      "text": "Square corners",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "tidy-1",
      "x": 540,
      "y": 185,
      "width": 240,
      "height": 130,
      "sketch": "tidy",
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#d3e1f5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "seed": 42,
      "text": "Soft corners",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.3
    },
    {
      "id": "tidy-2",
      "x": 830,
      "y": 185,
      "width": 240,
      "height": 130,
      "sketch": "tidy",
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#c6e6d5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "seed": 42,
      "text": "Round corners",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.7
    },
    {
      "id": "label-handwritten",
      "x": 42,
      "y": 375,
      "width": 190,
      "height": 130,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Handwritten",
      "fontSize": 25,
      "type": "text",
      "align": "left"
    },
    {
      "id": "handwritten-0",
      "x": 250,
      "y": 375,
      "width": 240,
      "height": 130,
      "sketch": "handwritten",
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#ffe3a0",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "seed": 42,
      "text": "Square corners",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "handwritten-1",
      "x": 540,
      "y": 375,
      "width": 240,
      "height": 130,
      "sketch": "handwritten",
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#d3e1f5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "seed": 42,
      "text": "Soft corners",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.3
    },
    {
      "id": "handwritten-2",
      "x": 830,
      "y": 375,
      "width": 240,
      "height": 130,
      "sketch": "handwritten",
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#c6e6d5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "seed": 42,
      "text": "Round corners",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.7
    },
    {
      "id": "label-loose",
      "x": 42,
      "y": 565,
      "width": 190,
      "height": 130,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Loose",
      "fontSize": 25,
      "type": "text",
      "align": "left"
    },
    {
      "id": "loose-0",
      "x": 250,
      "y": 565,
      "width": 240,
      "height": 130,
      "sketch": "loose",
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#ffe3a0",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "seed": 42,
      "text": "Square corners",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "loose-1",
      "x": 540,
      "y": 565,
      "width": 240,
      "height": 130,
      "sketch": "loose",
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#d3e1f5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "seed": 42,
      "text": "Soft corners",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.3
    },
    {
      "id": "loose-2",
      "x": 830,
      "y": 565,
      "width": 240,
      "height": 130,
      "sketch": "loose",
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#c6e6d5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "seed": 42,
      "text": "Round corners",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.7
    },
    {
      "id": "label-variation",
      "x": 42,
      "y": 755,
      "width": 190,
      "height": 130,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "New seed",
      "fontSize": 25,
      "type": "text",
      "align": "left"
    },
    {
      "id": "variation-17",
      "x": 250,
      "y": 755,
      "width": 240,
      "height": 130,
      "sketch": "handwritten",
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#ffe3a0",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "seed": 17,
      "text": "Seed 17",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.3
    },
    {
      "id": "variation-42",
      "x": 540,
      "y": 755,
      "width": 240,
      "height": 130,
      "sketch": "handwritten",
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#ffe3a0",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "seed": 42,
      "text": "Seed 42",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.3
    },
    {
      "id": "variation-99",
      "x": 830,
      "y": 755,
      "width": 240,
      "height": 130,
      "sketch": "handwritten",
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#ffe3a0",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "seed": 99,
      "text": "Seed 99",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.3
    }
  ]
}

Automatic process layout

Four labels become a complete hand-drawn flow. Longer flows wrap into rows automatically; choose vertical or horizontal when needed.

Automatic process layout, rendered by DrawFather

Try asking your agent: Use the process template to draw signup through first value.

Editable source · SVG image

Coordinate-free input (JSON file):

{
  "template": "process",
  "title": "From signup to first value",
  "steps": ["Sign up", "Verify email", "Create workspace", "First useful action"]
}
{
  "type": "drawfather",
  "revision": 0,
  "title": "From signup to first value",
  "seed": 42,
  "sketch": "handwritten",
  "canvas": {
    "width": 1264,
    "height": 341,
    "background": "#fffdf7"
  },
  "version": 2,
  "elements": [
    {
      "id": "df-title",
      "x": 64,
      "y": 64,
      "width": 1136,
      "height": 73,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "From signup to first value",
      "fontSize": 36,
      "type": "text",
      "align": "left"
    },
    {
      "id": "step-1",
      "x": 76.5,
      "y": 181,
      "width": 184,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#ffe3a0",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Sign up",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "step-2",
      "x": 385.5,
      "y": 181,
      "width": 184,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#d3e1f5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Verify email",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "step-3",
      "x": 687,
      "y": 181,
      "width": 199,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#c6e6d5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Create workspace",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "step-4",
      "x": 991,
      "y": 181,
      "width": 209,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#f5c8b6",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "First useful action",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "df-edge-1",
      "type": "arrow",
      "from": {
        "elementId": "step-1",
        "anchor": "right"
      },
      "to": {
        "elementId": "step-2",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "df-edge-2",
      "type": "arrow",
      "from": {
        "elementId": "step-2",
        "anchor": "right"
      },
      "to": {
        "elementId": "step-3",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "df-edge-3",
      "type": "arrow",
      "from": {
        "elementId": "step-3",
        "anchor": "right"
      },
      "to": {
        "elementId": "step-4",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    }
  ],
  "model": {
    "kind": "process",
    "direction": "auto",
    "origin": {
      "source": "composition",
      "composition": {
        "title": "From signup to first value",
        "seed": 42,
        "sketch": "handwritten",
        "roundness": 0.25,
        "template": "process",
        "direction": "auto",
        "steps": [
          "Sign up",
          "Verify email",
          "Create workspace",
          "First useful action"
        ]
      }
    },
    "nodes": [
      {
        "id": "step-1",
        "label": "Sign up",
        "shape": "rectangle",
        "role": "step"
      },
      {
        "id": "step-2",
        "label": "Verify email",
        "shape": "rectangle",
        "role": "step"
      },
      {
        "id": "step-3",
        "label": "Create workspace",
        "shape": "rectangle",
        "role": "step"
      },
      {
        "id": "step-4",
        "label": "First useful action",
        "shape": "rectangle",
        "role": "step"
      }
    ],
    "connections": [
      {
        "id": "df-edge-1",
        "from": "step-1",
        "to": "step-2",
        "role": "flow"
      },
      {
        "id": "df-edge-2",
        "from": "step-2",
        "to": "step-3",
        "role": "flow"
      },
      {
        "id": "df-edge-3",
        "from": "step-3",
        "to": "step-4",
        "role": "flow"
      }
    ],
    "groups": [],
    "annotations": [
      {
        "id": "df-title"
      }
    ]
  },
  "view": {
    "id": "main",
    "pins": [],
    "constraints": [],
    "intentionalOverlaps": []
  }
}

Automatic feedback loop

A compact Build-Measure-Learn request becomes a circular composition with curved arrows and measured lettering.

Automatic feedback loop, rendered by DrawFather

Try asking your agent: Use the cycle template to sketch Build, Measure, Learn with a short explanation of each step.

Editable source · SVG image

Coordinate-free input (JSON file):

{
  "template": "cycle",
  "title": "Build, Measure, Learn",
  "steps": [
    { "id": "build", "label": "Build", "detail": "Ship a small MVP" },
    { "id": "measure", "label": "Measure", "detail": "Observe behavior" },
    { "id": "learn", "label": "Learn", "detail": "Choose the next test" }
  ]
}
{
  "type": "drawfather",
  "revision": 0,
  "title": "Build, Measure, Learn",
  "seed": 42,
  "sketch": "handwritten",
  "canvas": {
    "width": 980,
    "height": 954,
    "background": "#fffdf7"
  },
  "version": 2,
  "elements": [
    {
      "id": "df-title",
      "x": 64,
      "y": 64,
      "width": 852,
      "height": 73,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Build, Measure, Learn",
      "fontSize": 36,
      "type": "text",
      "align": "left"
    },
    {
      "id": "build",
      "x": 387.5,
      "y": 281,
      "width": 205,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#ffe3a0",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Build\nShip a small MVP",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "measure",
      "x": 571.7798509084399,
      "y": 590.6557851430068,
      "width": 194,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#d3e1f5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Measure\nObserve behavior",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "learn",
      "x": 191.72014909156016,
      "y": 590.6557851430068,
      "width": 239,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#c6e6d5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Learn\nChoose the next test",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "df-edge-1",
      "type": "arrow",
      "from": {
        "elementId": "build",
        "anchor": "right"
      },
      "to": {
        "elementId": "measure",
        "anchor": "top"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": -90,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "df-edge-2",
      "type": "arrow",
      "from": {
        "elementId": "measure",
        "anchor": "bottom"
      },
      "to": {
        "elementId": "learn",
        "anchor": "bottom"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": -90,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "df-edge-3",
      "type": "arrow",
      "from": {
        "elementId": "learn",
        "anchor": "top"
      },
      "to": {
        "elementId": "build",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": -90,
      "text": "",
      "fontSize": 24
    }
  ],
  "model": {
    "kind": "cycle",
    "direction": "auto",
    "origin": {
      "source": "composition",
      "composition": {
        "title": "Build, Measure, Learn",
        "seed": 42,
        "sketch": "handwritten",
        "roundness": 0.25,
        "template": "cycle",
        "steps": [
          {
            "id": "build",
            "label": "Build",
            "detail": "Ship a small MVP",
            "shape": "rectangle"
          },
          {
            "id": "measure",
            "label": "Measure",
            "detail": "Observe behavior",
            "shape": "rectangle"
          },
          {
            "id": "learn",
            "label": "Learn",
            "detail": "Choose the next test",
            "shape": "rectangle"
          }
        ]
      }
    },
    "nodes": [
      {
        "id": "build",
        "label": "Build",
        "detail": "Ship a small MVP",
        "shape": "rectangle",
        "role": "step"
      },
      {
        "id": "measure",
        "label": "Measure",
        "detail": "Observe behavior",
        "shape": "rectangle",
        "role": "step"
      },
      {
        "id": "learn",
        "label": "Learn",
        "detail": "Choose the next test",
        "shape": "rectangle",
        "role": "step"
      }
    ],
    "connections": [
      {
        "id": "df-edge-1",
        "from": "build",
        "to": "measure",
        "role": "flow"
      },
      {
        "id": "df-edge-2",
        "from": "measure",
        "to": "learn",
        "role": "flow"
      },
      {
        "id": "df-edge-3",
        "from": "learn",
        "to": "build",
        "role": "flow"
      }
    ],
    "groups": [],
    "annotations": [
      {
        "id": "df-title"
      }
    ]
  },
  "view": {
    "id": "main",
    "pins": [],
    "constraints": [],
    "intentionalOverlaps": []
  }
}

Framework: Eric Ries, The Lean Startup methodology.

Automatic startup architecture

Nodes and connections become a layered system diagram. ELK positions the nodes, routes connectors, and places their labels; DrawFather draws rounded hand-sketched routes.

Automatic startup architecture, rendered by DrawFather

Try asking your agent: Use the architecture template for a web app, API, database, and background worker, with a customer entering through the app.

Editable source · SVG image

Coordinate-free input (JSON file):

{
  "template": "architecture",
  "title": "Our startup in one sketch",
  "nodes": [
    { "id": "customer", "label": "Customer", "shape": "ellipse" },
    { "id": "app", "label": "Web app", "detail": "The product interface" },
    { "id": "api", "label": "API", "detail": "Business logic" },
    { "id": "db", "label": "Database", "detail": "Product data" },
    { "id": "jobs", "label": "Worker", "detail": "Background jobs" }
  ],
  "connections": [
    { "from": "customer", "to": "app", "label": "visit" },
    { "from": "app", "to": "api", "label": "request" },
    { "from": "api", "to": "db", "label": "read / write" },
    { "from": "api", "to": "jobs", "label": "enqueue" }
  ]
}
{
  "type": "drawfather",
  "revision": 0,
  "title": "Our startup in one sketch",
  "seed": 42,
  "sketch": "handwritten",
  "canvas": {
    "width": 1718,
    "height": 554,
    "background": "#fffdf7"
  },
  "version": 2,
  "elements": [
    {
      "id": "df-title",
      "x": 64,
      "y": 64,
      "width": 1590,
      "height": 73,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Our startup in one sketch",
      "fontSize": 36,
      "type": "text",
      "align": "left"
    },
    {
      "id": "customer",
      "x": 88,
      "y": 207,
      "width": 271,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#ffe3a0",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Customer",
      "fontSize": 24,
      "type": "ellipse"
    },
    {
      "id": "app",
      "x": 551,
      "y": 207,
      "width": 242,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#d3e1f5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Web app\nThe product interface",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "api",
      "x": 1007,
      "y": 207,
      "width": 184,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#c6e6d5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "API\nBusiness logic",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "db",
      "x": 1441,
      "y": 207,
      "width": 184,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#f5c8b6",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Database\nProduct data",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "jobs",
      "x": 1441,
      "y": 367,
      "width": 189,
      "height": 96,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#e2d4ef",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Worker\nBackground jobs",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0.25
    },
    {
      "id": "df-edge-1",
      "type": "arrow",
      "from": {
        "elementId": "customer",
        "anchor": "right"
      },
      "to": {
        "elementId": "app",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "df-label-1",
      "x": 423,
      "y": 258,
      "width": 64,
      "height": 47,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "visit",
      "fontSize": 18,
      "type": "text",
      "align": "center"
    },
    {
      "id": "df-edge-2",
      "type": "arrow",
      "from": {
        "elementId": "app",
        "anchor": "right"
      },
      "to": {
        "elementId": "api",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "df-label-2",
      "x": 857,
      "y": 258,
      "width": 86,
      "height": 47,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "request",
      "fontSize": 18,
      "type": "text",
      "align": "center"
    },
    {
      "id": "df-edge-3",
      "type": "arrow",
      "from": {
        "elementId": "api",
        "anchor": "right"
      },
      "to": {
        "elementId": "db",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "df-label-3",
      "x": 1255,
      "y": 205,
      "width": 122,
      "height": 47,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "read / write",
      "fontSize": 18,
      "type": "text",
      "align": "center"
    },
    {
      "id": "df-edge-4",
      "type": "arrow",
      "from": {
        "elementId": "api",
        "anchor": "right"
      },
      "to": {
        "elementId": "jobs",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "waypoints": [
        [
          1223,
          255
        ],
        [
          1223,
          415
        ]
      ],
      "text": "",
      "fontSize": 24
    },
    {
      "id": "df-label-4",
      "x": 1270,
      "y": 418,
      "width": 92,
      "height": 47,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "enqueue",
      "fontSize": 18,
      "type": "text",
      "align": "center"
    }
  ],
  "model": {
    "kind": "architecture",
    "direction": "auto",
    "origin": {
      "source": "composition",
      "composition": {
        "title": "Our startup in one sketch",
        "seed": 42,
        "sketch": "handwritten",
        "roundness": 0.25,
        "template": "architecture",
        "direction": "auto",
        "nodes": [
          {
            "id": "customer",
            "label": "Customer",
            "shape": "ellipse"
          },
          {
            "id": "app",
            "label": "Web app",
            "detail": "The product interface",
            "shape": "rectangle"
          },
          {
            "id": "api",
            "label": "API",
            "detail": "Business logic",
            "shape": "rectangle"
          },
          {
            "id": "db",
            "label": "Database",
            "detail": "Product data",
            "shape": "rectangle"
          },
          {
            "id": "jobs",
            "label": "Worker",
            "detail": "Background jobs",
            "shape": "rectangle"
          }
        ],
        "connections": [
          {
            "from": "customer",
            "to": "app",
            "label": "visit"
          },
          {
            "from": "app",
            "to": "api",
            "label": "request"
          },
          {
            "from": "api",
            "to": "db",
            "label": "read / write"
          },
          {
            "from": "api",
            "to": "jobs",
            "label": "enqueue"
          }
        ]
      }
    },
    "nodes": [
      {
        "id": "customer",
        "label": "Customer",
        "shape": "ellipse",
        "role": "service"
      },
      {
        "id": "app",
        "label": "Web app",
        "detail": "The product interface",
        "shape": "rectangle",
        "role": "service"
      },
      {
        "id": "api",
        "label": "API",
        "detail": "Business logic",
        "shape": "rectangle",
        "role": "service"
      },
      {
        "id": "db",
        "label": "Database",
        "detail": "Product data",
        "shape": "rectangle",
        "role": "service"
      },
      {
        "id": "jobs",
        "label": "Worker",
        "detail": "Background jobs",
        "shape": "rectangle",
        "role": "service"
      }
    ],
    "connections": [
      {
        "id": "df-edge-1",
        "from": "customer",
        "to": "app",
        "role": "relationship",
        "label": "visit",
        "labelId": "df-label-1"
      },
      {
        "id": "df-edge-2",
        "from": "app",
        "to": "api",
        "role": "relationship",
        "label": "request",
        "labelId": "df-label-2"
      },
      {
        "id": "df-edge-3",
        "from": "api",
        "to": "db",
        "role": "relationship",
        "label": "read / write",
        "labelId": "df-label-3"
      },
      {
        "id": "df-edge-4",
        "from": "api",
        "to": "jobs",
        "role": "relationship",
        "label": "enqueue",
        "labelId": "df-label-4"
      }
    ],
    "groups": [],
    "annotations": [
      {
        "id": "df-title"
      }
    ]
  },
  "view": {
    "id": "main",
    "pins": [],
    "constraints": [],
    "intentionalOverlaps": []
  }
}

Lean Startup feedback loop

Build a small MVP, measure customer behavior, and use the learning to choose the next experiment.

Lean Startup feedback loop, rendered by DrawFather

Try asking your agent: Draw the Lean Startup Build-Measure-Learn feedback loop in a hand-drawn style.

Editable source · SVG image

{
  "type": "drawfather",
  "version": 1,
  "title": "Lean startup: Build, Measure, Learn",
  "seed": 17,
  "canvas": {"width": 1120, "height": 660, "background": "#fffdf7"},
  "elements": [
    {"id": "title", "type": "text", "x": 48, "y": 22, "width": 1024, "height": 72, "fontSize": 38, "text": "Lean startup: Build, Measure, Learn", "align": "left"},
    {"id": "subtitle", "type": "text", "x": 48, "y": 98, "width": 1024, "height": 48, "fontSize": 21, "text": "Turn one assumption into one small experiment.", "align": "left"},
    {"id": "build", "type": "rectangle", "x": 440, "y": 175, "width": 240, "height": 130, "text": "Build\nShip a small MVP", "fontSize": 24, "fill": "#ffe3a0"},
    {"id": "measure", "type": "rectangle", "x": 770, "y": 385, "width": 240, "height": 130, "text": "Measure\nObserve behavior", "fontSize": 24, "fill": "#d3e1f5"},
    {"id": "learn", "type": "rectangle", "x": 110, "y": 385, "width": 240, "height": 130, "text": "Learn\nPivot or persevere", "fontSize": 24, "fill": "#c6e6d5"},
    {"id": "build-to-measure", "type": "arrow", "from": {"elementId": "build", "anchor": "right"}, "to": {"elementId": "measure", "anchor": "top"}, "text": "data", "curve": -55},
    {"id": "measure-to-learn", "type": "arrow", "from": {"elementId": "measure", "anchor": "auto"}, "to": {"elementId": "learn", "anchor": "auto"}, "text": "insight", "curve": -55},
    {"id": "learn-to-build", "type": "arrow", "from": {"elementId": "learn", "anchor": "top"}, "to": {"elementId": "build", "anchor": "left"}, "curve": -55, "text": "next test"},
    {"id": "footer", "type": "text", "x": 60, "y": 575, "width": 1000, "height": 48, "fontSize": 23, "text": "Repeat the loop with what you learned.", "align": "center"}
  ]
}

Framework: Eric Ries, The Lean Startup methodology.

AARRR startup metrics

A familiar startup growth framework: Acquisition, Activation, Retention, Referral, and Revenue. The questions are illustrative, not benchmark data.

AARRR startup metrics, rendered by DrawFather

Try asking your agent: Draw an AARRR startup metrics funnel with one question for each stage.

Editable source · SVG image

{
  "type": "drawfather",
  "version": 1,
  "title": "AARRR: startup pirate metrics",
  "seed": 23,
  "canvas": {"width": 1120, "height": 820, "background": "#fffdf7"},
  "elements": [
    {"id": "title", "type": "text", "x": 48, "y": 22, "width": 1024, "height": 72, "fontSize": 38, "text": "AARRR: startup pirate metrics", "align": "left"},
    {"id": "subtitle", "type": "text", "x": 48, "y": 98, "width": 1024, "height": 48, "fontSize": 21, "text": "Five lenses on the customer journey.", "align": "left"},
    {"id": "acquisition", "type": "rectangle", "x": 80.0, "y": 170, "width": 560, "height": 80, "text": "01  Acquisition", "fontSize": 26, "fill": "#ffe3a0"},
    {"id": "acquisition-question", "type": "text", "x": 710, "y": 178, "width": 350, "height": 64, "fontSize": 22, "text": "How do people find you?", "align": "left"},
    {"id": "activation", "type": "rectangle", "x": 120.0, "y": 290, "width": 480, "height": 80, "text": "02  Activation", "fontSize": 26, "fill": "#d3e1f5"},
    {"id": "activation-question", "type": "text", "x": 710, "y": 298, "width": 350, "height": 64, "fontSize": 22, "text": "When do they first get value?", "align": "left"},
    {"id": "stage-1", "type": "arrow", "from": {"elementId": "acquisition", "anchor": "auto"}, "to": {"elementId": "activation", "anchor": "auto"}},
    {"id": "retention", "type": "rectangle", "x": 160.0, "y": 410, "width": 400, "height": 80, "text": "03  Retention", "fontSize": 26, "fill": "#c6e6d5"},
    {"id": "retention-question", "type": "text", "x": 710, "y": 418, "width": 350, "height": 64, "fontSize": 22, "text": "Do they come back?", "align": "left"},
    {"id": "stage-2", "type": "arrow", "from": {"elementId": "activation", "anchor": "auto"}, "to": {"elementId": "retention", "anchor": "auto"}},
    {"id": "referral", "type": "rectangle", "x": 200.0, "y": 530, "width": 320, "height": 80, "text": "04  Referral", "fontSize": 26, "fill": "#e2d4ef"},
    {"id": "referral-question", "type": "text", "x": 710, "y": 538, "width": 350, "height": 64, "fontSize": 22, "text": "Do they bring other people?", "align": "left"},
    {"id": "stage-3", "type": "arrow", "from": {"elementId": "retention", "anchor": "auto"}, "to": {"elementId": "referral", "anchor": "auto"}},
    {"id": "revenue", "type": "rectangle", "x": 240.0, "y": 650, "width": 240, "height": 80, "text": "05  Revenue", "fontSize": 26, "fill": "#f5c8b6"},
    {"id": "revenue-question", "type": "text", "x": 710, "y": 658, "width": 350, "height": 64, "fontSize": 22, "text": "Do they pay for that value?", "align": "left"},
    {"id": "stage-4", "type": "arrow", "from": {"elementId": "referral", "anchor": "auto"}, "to": {"elementId": "revenue", "anchor": "auto"}},
    {"id": "footer", "type": "text", "x": 70, "y": 755, "width": 980, "height": 45, "fontSize": 23, "text": "Choose a measurable event for each stage.", "align": "center"}
  ]
}

Framework: Dave McClure, Startup Metrics for Pirates.

SaaS MVP architecture

An illustrative startup architecture connecting a web app, API, database, background worker, and email provider.

SaaS MVP architecture, rendered by DrawFather

Try asking your agent: Sketch a simple SaaS MVP architecture, including background jobs and email notifications.

Editable source · SVG image

{
  "type": "drawfather",
  "revision": 1,
  "title": "A SaaS MVP architecture",
  "seed": 31,
  "canvas": {
    "width": 1240,
    "height": 760,
    "background": "#fffdf7"
  },
  "version": 1,
  "elements": [
    {
      "id": "title",
      "x": 48,
      "y": 22,
      "width": 1144,
      "height": 72,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "A SaaS MVP architecture",
      "fontSize": 38,
      "type": "text",
      "align": "left"
    },
    {
      "id": "subtitle",
      "x": 48,
      "y": 98,
      "width": 1144,
      "height": 48,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "From a customer request to background work.",
      "fontSize": 21,
      "type": "text",
      "align": "left"
    },
    {
      "id": "browser",
      "x": 60,
      "y": 220,
      "width": 220,
      "height": 120,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#ffe3a0",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Customer\nBrowser",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "app",
      "x": 425,
      "y": 220,
      "width": 240,
      "height": 120,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#d3e1f5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Web app\nProduct interface",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "api",
      "x": 825,
      "y": 220,
      "width": 240,
      "height": 120,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#c6e6d5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "API\nBusiness logic",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "database",
      "x": 825,
      "y": 510,
      "width": 240,
      "height": 120,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#e2d4ef",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Database\nProduct data",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "worker",
      "x": 425,
      "y": 510,
      "width": 240,
      "height": 120,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#f5c8b6",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Worker\nAsync jobs",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "email",
      "x": 60,
      "y": 510,
      "width": 220,
      "height": 120,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#ffe3a0",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Email provider\nNotifications",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "browser-to-app",
      "type": "arrow",
      "from": {
        "elementId": "browser",
        "anchor": "auto"
      },
      "to": {
        "elementId": "app",
        "anchor": "auto"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "HTTPS",
      "fontSize": 24
    },
    {
      "id": "app-to-api",
      "type": "arrow",
      "from": {
        "elementId": "app",
        "anchor": "right"
      },
      "to": {
        "elementId": "api",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "waypoints": [
        [
          699,
          280
        ],
        [
          791,
          280
        ]
      ],
      "text": "",
      "fontSize": 24
    },
    {
      "id": "api-to-database",
      "type": "arrow",
      "from": {
        "elementId": "api",
        "anchor": "auto"
      },
      "to": {
        "elementId": "database",
        "anchor": "auto"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "api-to-worker",
      "type": "arrow",
      "from": {
        "elementId": "api",
        "anchor": "left"
      },
      "to": {
        "elementId": "worker",
        "anchor": "top"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "worker-to-email",
      "type": "arrow",
      "from": {
        "elementId": "worker",
        "anchor": "auto"
      },
      "to": {
        "elementId": "email",
        "anchor": "auto"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "send",
      "fontSize": 24
    },
    {
      "id": "api-to-database-label",
      "x": 965,
      "y": 385,
      "width": 220,
      "height": 55,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "read / write",
      "fontSize": 22,
      "type": "text",
      "align": "center"
    },
    {
      "id": "api-to-worker-label",
      "x": 500,
      "y": 370,
      "width": 160,
      "height": 48,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "enqueue",
      "fontSize": 22,
      "type": "text",
      "align": "center"
    },
    {
      "id": "footer",
      "x": 60,
      "y": 680,
      "width": 1120,
      "height": 48,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Illustrative architecture. Adapt it to your product.",
      "fontSize": 22,
      "type": "text",
      "align": "center"
    },
    {
      "id": "df-label-e002cbb973d94289cd27",
      "x": 702,
      "y": 197,
      "width": 86,
      "height": 47,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "request",
      "fontSize": 18,
      "type": "text",
      "align": "center"
    }
  ]
}

CI/CD delivery pipeline

A common commit-to-production process with a test failure path that returns work to the build stage.

CI/CD delivery pipeline, rendered by DrawFather

Try asking your agent: Draw a CI/CD pipeline from commit to production, including a fix-and-retry path when tests fail.

Editable source · SVG image

{
  "type": "drawfather",
  "revision": 1,
  "title": "CI/CD: from commit to production",
  "seed": 43,
  "canvas": {
    "width": 1280,
    "height": 680,
    "background": "#fffdf7"
  },
  "version": 1,
  "elements": [
    {
      "id": "title",
      "x": 48,
      "y": 22,
      "width": 1184,
      "height": 72,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "CI/CD: from commit to production",
      "fontSize": 38,
      "type": "text",
      "align": "left"
    },
    {
      "id": "subtitle",
      "x": 48,
      "y": 98,
      "width": 1184,
      "height": 48,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "A delivery pipeline with an explicit quality gate.",
      "fontSize": 21,
      "type": "text",
      "align": "left"
    },
    {
      "id": "commit",
      "x": 50,
      "y": 250,
      "width": 170,
      "height": 130,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#ffe3a0",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Commit\nPush changes",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "build",
      "x": 300,
      "y": 250,
      "width": 170,
      "height": 130,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#d3e1f5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Build\nCreate artifact",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "test",
      "x": 550,
      "y": 250,
      "width": 170,
      "height": 130,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#e2d4ef",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Test\nCheck behavior",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "stage",
      "x": 800,
      "y": 250,
      "width": 170,
      "height": 130,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#f5c8b6",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Stage\nPreview release",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "production",
      "x": 1050,
      "y": 250,
      "width": 170,
      "height": 130,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#c6e6d5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Production\nRelease",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "fix",
      "x": 535,
      "y": 500,
      "width": 200,
      "height": 80,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#f5c8b6",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Fix & retry",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "commit-to-build",
      "type": "arrow",
      "from": {
        "elementId": "commit",
        "anchor": "auto"
      },
      "to": {
        "elementId": "build",
        "anchor": "auto"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "build-to-test",
      "type": "arrow",
      "from": {
        "elementId": "build",
        "anchor": "auto"
      },
      "to": {
        "elementId": "test",
        "anchor": "auto"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "test-to-stage",
      "type": "arrow",
      "from": {
        "elementId": "test",
        "anchor": "right"
      },
      "to": {
        "elementId": "stage",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "waypoints": [
        [
          754,
          315
        ],
        [
          766,
          315
        ]
      ],
      "text": "",
      "fontSize": 24
    },
    {
      "id": "stage-to-production",
      "type": "arrow",
      "from": {
        "elementId": "stage",
        "anchor": "auto"
      },
      "to": {
        "elementId": "production",
        "anchor": "auto"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "test-to-fix",
      "type": "arrow",
      "from": {
        "elementId": "test",
        "anchor": "bottom"
      },
      "to": {
        "elementId": "fix",
        "anchor": "top"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "test-to-fix-label",
      "x": 650,
      "y": 410,
      "width": 100,
      "height": 48,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "fail",
      "fontSize": 22,
      "type": "text",
      "align": "center"
    },
    {
      "id": "fix-to-build",
      "type": "arrow",
      "from": {
        "elementId": "fix",
        "anchor": "left"
      },
      "to": {
        "elementId": "build",
        "anchor": "bottom"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": -70,
      "text": "retry",
      "fontSize": 24
    },
    {
      "id": "footer",
      "x": 50,
      "y": 615,
      "width": 1180,
      "height": 47,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Example stages; your team can add its own checks and approvals.",
      "fontSize": 21,
      "type": "text",
      "align": "center"
    },
    {
      "id": "df-label-c46d198461a1446bd777",
      "x": 720,
      "y": 232,
      "width": 80,
      "height": 47,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "pass",
      "fontSize": 18,
      "type": "text",
      "align": "center"
    }
  ]
}

Customer onboarding decision tree

A signup flow with an email-verification decision, a resend-and-retry path, and the first useful product action.

Customer onboarding decision tree, rendered by DrawFather

Try asking your agent: Draw customer onboarding from signup to first value, with an email-verification decision and retry path.

Editable source · SVG image

{
  "type": "drawfather",
  "revision": 1,
  "title": "Customer onboarding: the first useful action",
  "seed": 59,
  "canvas": {
    "width": 1120,
    "height": 790,
    "background": "#fffdf7"
  },
  "version": 1,
  "elements": [
    {
      "id": "title",
      "x": 48,
      "y": 22,
      "width": 1024,
      "height": 72,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Customer onboarding: the first useful action",
      "fontSize": 38,
      "type": "text",
      "align": "left"
    },
    {
      "id": "subtitle",
      "x": 48,
      "y": 98,
      "width": 1024,
      "height": 48,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "A decision tree with a recovery path.",
      "fontSize": 21,
      "type": "text",
      "align": "left"
    },
    {
      "id": "signup",
      "x": 60,
      "y": 200,
      "width": 200,
      "height": 100,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#ffe3a0",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Sign up",
      "fontSize": 24,
      "type": "ellipse"
    },
    {
      "id": "verified",
      "x": 400,
      "y": 165,
      "width": 260,
      "height": 220,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#d3e1f5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Email\nverified?",
      "fontSize": 24,
      "type": "diamond"
    },
    {
      "id": "workspace",
      "x": 820,
      "y": 200,
      "width": 220,
      "height": 100,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#c6e6d5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Create workspace",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "resend",
      "x": 420,
      "y": 520,
      "width": 220,
      "height": 110,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#f5c8b6",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Resend email",
      "fontSize": 24,
      "type": "rectangle",
      "roundness": 0
    },
    {
      "id": "value",
      "x": 820,
      "y": 520,
      "width": 220,
      "height": 126,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "#c6e6d5",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "First useful\naction",
      "fontSize": 24,
      "type": "ellipse"
    },
    {
      "id": "signup-to-verified",
      "type": "arrow",
      "from": {
        "elementId": "signup",
        "anchor": "auto"
      },
      "to": {
        "elementId": "verified",
        "anchor": "auto"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "verified-to-workspace",
      "type": "arrow",
      "from": {
        "elementId": "verified",
        "anchor": "right"
      },
      "to": {
        "elementId": "workspace",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "waypoints": [
        [
          694,
          275
        ],
        [
          786,
          275
        ],
        [
          786,
          250
        ]
      ],
      "text": "",
      "fontSize": 24
    },
    {
      "id": "verified-to-resend",
      "type": "arrow",
      "from": {
        "elementId": "verified",
        "anchor": "bottom"
      },
      "to": {
        "elementId": "resend",
        "anchor": "top"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "text": "",
      "fontSize": 24
    },
    {
      "id": "resend-to-verified",
      "type": "arrow",
      "from": {
        "elementId": "resend",
        "anchor": "left"
      },
      "to": {
        "elementId": "verified",
        "anchor": "left"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": -65,
      "text": "retry",
      "fontSize": 24
    },
    {
      "id": "workspace-to-value",
      "type": "arrow",
      "from": {
        "elementId": "workspace",
        "anchor": "bottom"
      },
      "to": {
        "elementId": "value",
        "anchor": "top"
      },
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "curve": 0,
      "waypoints": [
        [
          930,
          334
        ],
        [
          930,
          486
        ]
      ],
      "text": "",
      "fontSize": 24
    },
    {
      "id": "verified-to-resend-label",
      "x": 545,
      "y": 415,
      "width": 75,
      "height": 48,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "no",
      "fontSize": 22,
      "type": "text",
      "align": "center"
    },
    {
      "id": "footer",
      "x": 60,
      "y": 705,
      "width": 1000,
      "height": 50,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "Guide the happy path. Make recovery clear.",
      "fontSize": 23,
      "type": "text",
      "align": "center"
    },
    {
      "id": "df-label-f5a4e8d6a8839b1b6852",
      "x": 700,
      "y": 192,
      "width": 80,
      "height": 47,
      "stroke": "#252525",
      "strokeWidth": 2,
      "fill": "transparent",
      "fillStyle": "hachure",
      "roughness": 1.2,
      "text": "yes",
      "fontSize": 18,
      "type": "text",
      "align": "center"
    }
  ]
}

Kanban board

A three-column work board showing startup tasks moving from To do to In progress to Done.

Kanban board, rendered by DrawFather

Try asking your agent: Draw a hand-sketched Kanban board for a startup MVP with To do, In progress, and Done columns.

Editable source · SVG image

{
  "type": "drawfather",
  "version": 1,
  "title": "Kanban: make the work visible",
  "seed": 71,
  "canvas": {"width": 1200, "height": 720, "background": "#fffdf7"},
  "elements": [
    {"id": "title", "type": "text", "x": 48, "y": 22, "width": 1104, "height": 72, "fontSize": 38, "text": "Kanban: make the work visible", "align": "left"},
    {"id": "subtitle", "type": "text", "x": 48, "y": 98, "width": 1104, "height": 48, "fontSize": 21, "text": "One task, one column, one next step.", "align": "left"},
    {"id": "todo-column", "type": "rectangle", "x": 60, "y": 190, "width": 320, "height": 420, "text": "", "fontSize": 24, "fill": "transparent"},
    {"id": "doing-column", "type": "rectangle", "x": 440, "y": 190, "width": 320, "height": 420, "text": "", "fontSize": 24, "fill": "transparent"},
    {"id": "done-column", "type": "rectangle", "x": 820, "y": 190, "width": 320, "height": 420, "text": "", "fontSize": 24, "fill": "transparent"},
    {"id": "todo-title", "type": "text", "x": 80, "y": 210, "width": 280, "height": 65, "fontSize": 30, "text": "To do", "align": "center"},
    {"id": "doing-title", "type": "text", "x": 460, "y": 210, "width": 280, "height": 65, "fontSize": 30, "text": "In progress", "align": "center"},
    {"id": "done-title", "type": "text", "x": 840, "y": 210, "width": 280, "height": 65, "fontSize": 30, "text": "Done", "align": "center"},
    {"id": "interview", "type": "rectangle", "x": 85, "y": 300, "width": 270, "height": 95, "text": "Interview users", "fontSize": 24, "fill": "#ffe3a0"},
    {"id": "sketch", "type": "rectangle", "x": 85, "y": 430, "width": 270, "height": 95, "text": "Sketch onboarding", "fontSize": 24, "fill": "#ffe3a0"},
    {"id": "mvp", "type": "rectangle", "x": 465, "y": 300, "width": 270, "height": 95, "text": "Build the MVP", "fontSize": 24, "fill": "#d3e1f5"},
    {"id": "limit", "type": "text", "x": 465, "y": 445, "width": 270, "height": 60, "fontSize": 20, "text": "Limit work in progress", "align": "center"},
    {"id": "problem", "type": "rectangle", "x": 845, "y": 300, "width": 270, "height": 95, "text": "Define the problem", "fontSize": 24, "fill": "#c6e6d5"},
    {"id": "hypothesis", "type": "rectangle", "x": 845, "y": 430, "width": 270, "height": 95, "text": "Pick one hypothesis", "fontSize": 24, "fill": "#c6e6d5"},
    {"id": "to-doing", "type": "arrow", "from": [390, 245], "to": [430, 245]},
    {"id": "to-done", "type": "arrow", "from": [770, 245], "to": [810, 245]},
    {"id": "footer", "type": "text", "x": 60, "y": 640, "width": 1080, "height": 45, "fontSize": 23, "text": "Move cards as work progresses.", "align": "center"}
  ]
}

Straight and curved arrows

Compare curve: 0, curve: 60, and curve: -60. Curved arrowheads follow the arrival tangent, and labels follow the bow.

Straight and curved arrows, rendered by DrawFather

Try asking your agent: Draw three connections comparing a straight arrow, a downward-bowed arrow, and an upward-bowed arrow.

Editable source · SVG image

{
  "type": "drawfather",
  "version": 1,
  "title": "Straight and curved arrows",
  "seed": 83,
  "canvas": {"width": 1120, "height": 810, "background": "#fffdf7"},
  "elements": [
    {"id": "title", "type": "text", "x": 48, "y": 22, "width": 1024, "height": 72, "fontSize": 38, "text": "A softer way to connect ideas"},
    {"id": "subtitle", "type": "text", "x": 48, "y": 98, "width": 1024, "height": 48, "fontSize": 21, "text": "One optional curve field. Three different connections."},
    {"id": "straight-start", "type": "rectangle", "x": 80, "y": 185, "width": 210, "height": 90, "text": "Start", "fill": "#ffe3a0"},
    {"id": "straight-finish", "type": "rectangle", "x": 820, "y": 185, "width": 210, "height": 90, "text": "Finish", "fill": "#ffe3a0"},
    {"id": "straight-arrow", "type": "arrow", "from": {"elementId": "straight-start"}, "to": {"elementId": "straight-finish"}, "curve": 0, "text": "curve: 0"},
    {"id": "down-start", "type": "rectangle", "x": 80, "y": 355, "width": 210, "height": 90, "text": "Start", "fill": "#d3e1f5"},
    {"id": "down-finish", "type": "rectangle", "x": 820, "y": 355, "width": 210, "height": 90, "text": "Finish", "fill": "#d3e1f5"},
    {"id": "down-arrow", "type": "arrow", "from": {"elementId": "down-start"}, "to": {"elementId": "down-finish"}, "curve": 60, "text": "curve: 60"},
    {"id": "up-start", "type": "rectangle", "x": 80, "y": 605, "width": 210, "height": 90, "text": "Start", "fill": "#c6e6d5"},
    {"id": "up-finish", "type": "rectangle", "x": 820, "y": 605, "width": 210, "height": 90, "text": "Finish", "fill": "#c6e6d5"},
    {"id": "up-arrow", "type": "arrow", "from": {"elementId": "up-start"}, "to": {"elementId": "up-finish"}, "curve": -60, "text": "curve: -60"},
    {"id": "footer", "type": "text", "x": 60, "y": 735, "width": 1000, "height": 50, "fontSize": 22, "align": "center", "text": "A signed bend in pixels. Zero keeps the arrow straight."}
  ]
}

Status

An early, local-first implementation. The engine reads native v1 and v2; new compositions use semantic v2. The project has not reached a stable 1.0 release. It is not yet published to npm. Hosted accounts and billing are outside this initial release.

The launch roadmap covers semantic editing, layout preservation, visual checks, documentation workflows, technical and creative diagram types, interoperability, and release verification. Every phase is required before the public product launch. Features listed there remain planned until their acceptance criteria are met.

Run from source

Requires Node.js 22 or newer and npm.

npm ci
npm run build
node dist/cli.js --help

Generate a real sample and ready-to-paste client settings:

npm run demo
npm run demo -- --template cycle
npm run demo -- --template architecture
node dist/cli.js setup --directory /absolute/path/to/my-drawings

demo prints the saved source, PNG, and SVG paths and chooses a fresh filename each time. setup prints JSON containing the absolute Node executable, installed server path, and storage directory. Copy that JSON into a client that supports MCP stdio configuration; adapt the wrapper to your client's settings format if needed. npm run setup is a shortcut for the default drawing directory; npm also prints its script banner, so use node dist/cli.js setup when capturing only JSON. Inspect the template catalog with node dist/cli.js templates.

The storage folder can also be set through DRAWFATHER_DIR. Without either setting it defaults to ./drawings relative to the server's working directory. Use an absolute folder path in your client configuration so your files are easy to find.

Try asking your assistant:

Use DrawFather’s process template for a product launch: Build, Test, Ship. Show the preview and export SVG. Then rename Test to Customer validation while preserving the layout.

DrawFather runs over stdin/stdout. Running the server directly will wait for an MCP client; it does not open a web page. It sends no drawing content to an external service. Your chosen AI client may process that content according to its own settings.

Your source file

A .drawfather file is plain JSON. Native v2 retains semantic nodes, connections, groups, annotations, and a constrained view alongside its rendered elements. Existing v1 files keep the simpler geometry-only structure shown below.

{
  "type": "drawfather",
  "version": 1,
  "title": "My first sketch",
  "seed": 42,
  "canvas": {
    "width": 800,
    "height": 400,
    "background": "#fffdf7"
  },
  "elements": [
    {
      "id": "idea",
      "type": "rectangle",
      "x": 60,
      "y": 140,
      "width": 230,
      "height": 120,
      "text": "An idea",
      "fill": "#ffdf80"
    },
    {
      "id": "sketch",
      "type": "ellipse",
      "x": 500,
      "y": 140,
      "width": 230,
      "height": 120,
      "text": "A sketch",
      "fill": "#b8e0cc"
    },
    {
      "id": "connection",
      "type": "arrow",
      "from": { "elementId": "idea" },
      "to": { "elementId": "sketch" },
      "text": "DrawFather"
    }
  ]
}

Save the source, put it in Git, share it, or edit it with any text editor or AI agent. All supported exports are available locally. To open an existing file through MCP, place it in the configured storage folder with an identifier as its filename, such as first-sketch.drawfather, and call get_drawing with name: "first-sketch".

The published v1 schema and v2 schema describe both structures. Runtime validation additionally checks unique element IDs and valid arrow bindings. The format is native to DrawFather. The interchange support matrix describes implemented Mermaid, Excalidraw and draw.io conversion, explicit loss reports and optional native embedding. Use import_drawing / export_interchange; Phase 6 evidence records actual editor round trips.

Elements and styles

Type

Fields

rectangle, ellipse, diamond

id, x, y, width, height; optional text, fontSize

text

Same box fields; optional align: left, center, right

container (v2)

Box fields plus padding; managed through semantic groups

arrow

id, from, to; optional curve, text, fontSize

freedraw

id, points: at least two [x, y] pairs, rendered as a smooth sketch curve

All elements accept stroke, strokeWidth, fill, fillStyle, roughness, seed, and an optional sketch preset override. Rectangles additionally accept roundness. Colors are #rgb, #rrggbb, or transparent. Fill styles are hachure, solid, cross-hatch, and dots. Roughness ranges from 0.5 to 3. Coordinates are pixels; box x/y always refers to the top-left, including ellipses and diamonds. Keep content inside the canvas, allowing margins for rough strokes.

Arrow endpoints accept an explicit [x, y] pair or { "elementId": "idea", "anchor": "auto" }. Supported anchors are auto, top, right, bottom, and left. Bound arrows attach outside shape borders and follow moved elements. They render behind other elements. Architecture composition and affected semantic connections support obstacle routing. Self-loops remain unsupported.

Curved arrows

Set curve to a signed bend in pixels. The default is 0, which keeps the arrow straight. A positive value bends toward the right as you follow the arrow; a negative value bends toward the left. For a left-to-right arrow, 60 bows down and -60 bows up. The magnitude is the curve's midpoint offset from the straight line between its resolved endpoints. Supported values range from -4096 to 4096.

{
  "id": "connection",
  "type": "arrow",
  "from": { "elementId": "idea" },
  "to": { "elementId": "sketch" },
  "curve": -60,
  "text": "Build it"
}

The renderer uses a quadratic Bezier curve with a hand-drawn stroke. The arrowhead follows the tangent at the end, and its label sits outside the bow at the curve's midpoint. Bound endpoints retain their selected anchors. Leave room around curves and labels; use explicit anchors or separate text elements to refine the layout. See the straight-and-curved comparison for complete source. Existing drawings without curve continue to render straight arrows.

The document seed and each element's ID produce stable sketch strokes. Explicit element seeds override that behavior. Changing another element does not randomize the whole drawing.

Lettering uses the included Kalam Latin font. Text wraps and shrinks down to 12px when needed; labels that cannot fit return an error so the agent can enlarge the box. Unsupported glyphs return an explicit error. Text is converted to outlines for consistent exports without system fonts; the editable text stays in .drawfather, and SVG titles preserve labels for accessibility. SVG lettering is not directly editable as SVG text.

Native files limit a drawing to 500 elements, 1,000 points per freehand element, 5 MB of source JSON, and a canvas of at most 16 million pixels with either dimension at most 8,192. The general composition templates, ten typed technical families and eight creative families provide layout; native source retains explicit coordinates. The documented subset supports Mermaid import and editable Excalidraw/draw.io handoffs. Local embedded fonts and images, supported shape rotation and vector PDF are implemented; see the creative contract for their boundaries. A hosted HTTP transport remains future work. Native v2 supports nested groups and layout constraints. Large compositions can exceed the canvas limits; shorten labels, change direction, or split them into smaller diagrams. Arbitrary manually positioned shapes do not receive automatic obstacle routing.

Routed connectors

Architecture compositions use ELK to route connections and place edge labels. Native arrows support an optional waypoints array of 1–32 absolute interior [x, y] positions. The renderer rounds the corners of that route. Omit curve, or leave it at zero, when using waypoints. Endpoints can still bind to shapes; interior route points stay at their saved coordinates. Semantic edits and supported v2 manual updates refresh affected routes. V1 raw geometry keeps its saved interior points; migrate it before using semantic editing.

MCP tools

Tool

Purpose

list_templates

Discover process, cycle, and architecture inputs

compose_technical

Compose ten typed technical families with symbols, views, callouts and legends

get_capabilities

Concise discovery of templates, primitives/roles, styles, operations, and examples

compose_drawing

Automatically lay out a diagram and return compact saved-state metadata

get_format

JSON schema plus a minimal source example

list_drawings

Names of saved .drawfather files

create_drawing

Save a new drawing; never overwrite an existing one

get_drawing

Summary, paged elements/graph, or explicit full source

edit_drawing

Atomic semantic edits, pins, groups, constraints, and saved-model reflow

patch_drawing

Small label/detail/style patches without resending geometry

migrate_drawing

Upgrade v1 to v2 with an exact original backup

drawing_history

List local history and backups; undo, redo, or restore a commit

check_drawing

Structured visual diagnostics and corrections without changing source

repair_drawing

Preview a bounded repair, then apply the exact reviewed plan as one revision

update_drawing

Replace or remove elements, update title/seed/sketch/canvas, check revision

preview_drawing

Read-only PNG with size, region, selection, and background controls

compose_creative

Eight typed creative/planning families; reuse saved templates and style/component libraries

edit_creative

Branch, schedule, journey, board, annotation and panel edits with stable IDs

set_presentation

Embed local images/fonts; apply brand presets, glyph fallback and text alternatives

export_drawing

Stable/revisioned SVG, PNG, JPG, WebP, vector PDF with theme/scale settings and optional metadata

project_diagrams

Manifest-based rendering, doc links/sync, freshness, affected diagrams, review diffs and acknowledgements

Mutations default to compact structured metadata. Request includeSource: true for full JSON and preview: true or preview options for a PNG. get_drawing defaults to a summary; its source view retrieves complete source. Exports write full-resolution files and default to metadata-only delivery. See agent API options.

Native schemas are also available as MCP resources at drawfather://schema/v1 and drawfather://schema/v2. get_format returns the current schema, a v2 example, and the legacy schema.

Creation starts at revision 1. An update requires expectedRevision, obtained by reading the drawing first. upsert contains complete elements, replacing existing elements by ID or appending new ones. remove contains element IDs. For v1 raw updates, remove a shape and its bound arrows together. V2 reconciliation removes a deleted semantic node's connections and owned labels; pins still require explicit unpin before removal. Imported files without a revision start at 0, which is accepted as expectedRevision.

{
  "name": "first-sketch",
  "expectedRevision": 1,
  "upsert": [
    {
      "id": "idea",
      "type": "rectangle",
      "x": 60,
      "y": 140,
      "width": 230,
      "height": 120,
      "text": "A better idea",
      "fill": "#ffdf80"
    }
  ]
}

Exports include the source revision in the filename, such as first-sketch.r2.svg. Your .drawfather source is retained. PNG and WebP support a transparent canvas; JPEG flattens transparency onto white. Display of inline previews depends on the MCP client.

Writes are atomic, updates check revisions, and per-drawing lock files prevent concurrent edits from silently overwriting one another. If a process crashes during an update, it may leave a .lock file: after confirming no DrawFather process is editing that drawing, remove that lock file and retry. If you manually edit a managed source file, increment its revision to invalidate stale agent updates and keep its v2 model consistent with its elements. An external edit starts a new history branch unless it matches an existing canonical snapshot. Copy .drawfather-history/ and .drawfather-backups/ with the source when transferring managed history. A source file alone remains portable and renderable.

Use as a library

After building, local code can import the engine directly:

import { readFile, writeFile } from 'node:fs/promises';
import { composeDrawing, exportDrawing, parseDrawing } from './dist/index.js';

const drawing = await composeDrawing({
  template: 'process', title: 'Product launch', steps: ['Build', 'Test', 'Ship'],
});
await writeFile('my-sketch.drawfather', JSON.stringify(drawing, null, 2));
// Existing source: parseDrawing(JSON.parse(await readFile('my-sketch.drawfather', 'utf8')));
await writeFile('my-sketch.svg', await exportDrawing(drawing, 'svg'));
await writeFile('my-sketch.png', await exportDrawing(drawing, 'png'));

Development

npm run build
npm test
npm run schema -- --check
npm run example
npm run gallery -- --check
npm pack --dry-run

npm run example first composes the three automatic examples from examples/compositions/*.json, generates the sketch comparison, semantic edit example, and visual repair example, and then renders every .drawfather file in examples/ into SVG, PNG, JPG, and WebP in output/, refreshes the SVGs in examples/, and updates the README gallery from examples/gallery.json and the actual source files. Edit a source file, then rerun this command to keep its image and code block in sync. npm run gallery -- --check verifies that the README embeds the current source. Tests cover validation, deterministic rendering, migration, semantic edits, groups, constraints, visual checks and repair limits, exact-plan application, export dimensions, history and write-failure recovery, revisions, storage boundaries, and real MCP client workflows. The test command runs a build first.

The example pipeline also builds the root gallery manifest/receipt and the illustrative project under examples/project/. Its known sample code and diagram are generated together; generic project rendering never acknowledges changed code. Run npm run docs:check after regeneration. The engine uses TypeScript, ELK, Rough.js, OpenType.js, Sharp, Zod, and the official MCP TypeScript SDK. Rendering requires no browser. Read CONTRIBUTING.md for the project scope and contribution workflow.

License

The engine and repository files are licensed under Elastic License 2.0, except schema/ and examples/, which each include an MIT license. DrawFather is source-available / fair-code; the engine is not OSI open source.

You can self-host and modify the engine, including for internal business use, subject to ELv2. Offering substantial DrawFather functionality to third parties as a hosted or managed service requires separate permission from the relevant copyright holders. Access through MCP, an API, or an AI assistant can fall within this restriction. Commercial integrations depend on the functionality made available; they are not all prohibited. See LICENSING.md for examples.

Using DrawFather does not impose the engine license on your own drawing content or its .drawfather, SVG, PNG, JPG, WebP, or PDF exports. Third-party content and assets retain their own terms. Kalam is by Indian Type Foundry and uses the SIL Open Font License 1.1. Dependencies retain their own licenses; see THIRD_PARTY_NOTICES.md.

Available Tools

23 tools
check_drawingC
Read-only

Inspect visual quality and page diagnostics. Reports global counts and completeness even when findings are filtered by ids or severity. Cursors bind source, checks and filters.

ParametersJSON Schema
NameRequiredDescriptionDefault
idsNo
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
limitNo
checksNo
cursorNo
severityNo

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds genuinely useful behavior beyond that: global counts and completeness are reported even when findings are filtered, and cursors are bound to source+checks+filters. It stops short of describing finding shape, ordering, or pagination semantics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences with the core purpose front-loaded and no filler. The final sentence about cursors is terse to the point of being cryptic, but nothing is padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists and parameter documentation is sparse, so the description carries the burden for a fairly complex inspection tool. It explains filtering and cursor behavior but leaves the checks configuration, limits, result structure, and severity semantics unexplained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 17% on six parameters, including a nine-property nested 'checks' object that is completely undocumented. The description only gestures at two of them ('ids or severity' filters, 'cursor' binding) and never explains the name/limit/checks configuration, so it does not compensate for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Inspect') and a concrete resource ('visual quality and page diagnostics') tied to the drawing named in the tool name, which separates it from compose_/edit_/export_ siblings. It does not explicitly name the drawing artifact as the primary object, but the name and the 'page diagnostics' phrase make it inferable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives no when-to-use guidance and never points to an alternative such as preview_drawing or repair_drawing, so an agent cannot tell whether this is the diagnostic step before repair or a standalone check. The only contextual hint is that filtering does not suppress the global summary.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

compose_creativeA
Destructive

Create mindmap, gantt, timeline, journey, kanban, annotated sketch, storyboard or wireframe. Read drawfather://schema/creative and drawfather://creative. reuseFrom optionally inherits a saved creative template, components and brand/font settings; design overrides selected top-level fields. Existing destination requires expectedRevision.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
designYes
previewNo
reuseFromNo
includeSourceNo
expectedRevisionNo

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare a destructive, non-read-only write, and the description meaningfully adds to that: overwriting an existing destination requires expectedRevision, and reuseFrom inherits template/components/brand settings while design overrides top-level fields. It still does not say what is destroyed or how the existing file is affected when expectedRevision is omitted.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the artifact list, then prerequisites, then the two optional behaviors, in four dense but waste-free sentences. No filler or restatement of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter destructive mutation with no output schema and an opaque nested design object, the description covers the core contract but leaves preview/includeSource and the actual overwrite consequence unexplained. Adequate, not complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 17%, so the description must compensate and partially does: design, reuseFrom, and expectedRevision are all explained with semantics the schema lacks (design is an opaque additionalProperties object otherwise). But preview and includeSource get no explanation anywhere, leaving two number-or-object parameters undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb ('Create') and enumerates the concrete creative artifacts it produces (mindmap, gantt, timeline, journey, kanban, sketch, storyboard, wireframe). This clearly separates it from siblings like compose_drawing, compose_technical, and compose_diagram without needing to open any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a concrete prerequisite ('Read drawfather://schema/creative and drawfather://creative') and states the condition for expectedRevision (existing destination). It does not, however, explicitly contrast itself with compose_technical or compose_drawing, so the agent must infer which sibling to pick.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

compose_drawingB
Destructive

Create process/cycle/architecture from steps or a graph. Metadata is compact by default; opt into includeSource and preview. Provide expectedRevision only for explicit replacement. Example: get_capabilities topic examples.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
designYes
previewNo
includeSourceNo
expectedRevisionNo

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false. The description adds meaningful context—metadata is compact unless includeSource/preview are opted into, and expectedRevision is reserved for replacement—but it doesn't explain what a destructive create overwrites or the effect of the revision guard.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core action, with the opt-in defaults and revision rule packed efficiently. The trailing 'Example: get_capabilities topic examples' is somewhat cryptic and slightly muddies the ending.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a complex tool—five parameters with nested oneOf branches (steps/nodes/connections), no output schema, and low schema coverage—yet the description gives only a few lines. It omits how the templates differ behaviorally and what a successful call returns or does to existing files.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 20%, so the description must carry more burden. It does mention includeSource, preview, and expectedRevision semantics, but 'name' and the large 'design' object are left to the schema, and 'from steps or a graph' only loosely maps to the design oneOf.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: 'Create process/cycle/architecture from steps or a graph,' naming the three template variants and the two input shapes. It does not distinguish itself from close siblings like compose_technical or compose_creative, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Provide expectedRevision only for explicit replacement' is a real usage rule, and the pointer to get_capabilities for examples gives the agent a next step. However, there is no guidance on when to pick this over compose_technical/compose_creative, so usage is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

compose_technicalA
Destructive

Create typed flowchart, sequence, C4, ER, state, class, dataflow, dependency, activity or deployment drawings. Discover get_capabilities topic technical and read drawfather://schema/technical for exact fields. Nodes and connections need typed notation. Existing files require expectedRevision for explicit replacement.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
designYes
previewNo
includeSourceNo
expectedRevisionNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With destructiveHint=true already declared, the description adds real value by explaining the concrete destructive mechanism: replacing an existing file requires expectedRevision for 'explicit replacement', and it notes the typed-notation constraint. It does not disclose what happens on a revision mismatch or the scope of what gets overwritten, keeping it below 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, front-loaded with the creation purpose, followed by the discovery pointer and the replacement constraint. The diagram-type enumeration is somewhat long but serves routing value; no sentence is purely filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, nested-object mutation tool with 20% schema coverage and no output schema, the description strategically defers exact field requirements to the drawfather://schema/technical resource and flags the key destructive precondition. Preview and includeSource remain undocumented, but the deferral to an authoritative schema keeps it largely complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 20%, so the description carries a heavier burden. It adds meaning for expectedRevision (replacement guard) and design (typed nodes/connections), but preview and includeSource go entirely unexplained in both schema and description, so it only partially compensates.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb ('Create') plus a well-scoped resource ('typed flowchart, sequence, C4, ER, state, class, dataflow, dependency, activity or deployment drawings'), which clearly places it in the technical-diagram domain. It distinguishes itself from compose_creative by the enumerated technical diagram types, though it never explicitly contrasts itself with the generic compose_drawing sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides a concrete workflow ('Discover get_capabilities topic technical and read drawfather://schema/technical for exact fields') and a conditional requirement ('Existing files require expectedRevision for explicit replacement'). It lacks an explicit when-not or named-alternative comparison against compose_drawing/compose_creative, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_drawingB

Save native source without overwriting. For exact native fields read drawfather://schema/v2 or get_format; the engine validates that full schema before writing. Metadata is compact; includeSource and preview are opt-in.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
drawingYes
previewNo
includeSourceNo

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false), and the description usefully reinforces that with 'without overwriting' and adds that the engine validates the full schema before writing. It omits what happens on a name collision, whether writes are atomic, or required permissions, so there is added context but meaningful behavioral gaps remain.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the non-overwriting constraint, then the schema reference, then the opt-in flags. No filler, though the inline drawfather:// URI is dense and slightly interrupts flow.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given nested arbitrary `drawing` content and no output schema, the description covers where to find the exact schema and the opt-in params, but says nothing about the return value or post-write behavior, and doesn't situate the tool relative to compose/edit/import siblings. Adequate but incomplete for a create primitive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 25% (only `name` is documented), so the description must compensate. It does partially: 'includeSource and preview are opt-in' conveys the semantics and defaults of two otherwise-undocumented params, and 'Metadata is compact' hints at the `drawing` payload. The arbitrary `drawing` object body remains opaque.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (save/create) and resource (native source/drawing) with the crucial constraint 'without overwriting', which cleanly separates it from the mutation siblings update_drawing, patch_drawing and edit_drawing. It stops just short of naming those alternatives, but the scope is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives some routing guidance by pointing to get_format (and a schema URI) for exact native fields, and flags includeSource/preview as opt-in. However, it never says when to choose create_drawing over compose_drawing or import_drawing, so the create-vs-compose decision is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

drawing_historyA
Destructive

List bounded local history or undo/redo/restore as a new revision. Mutations require expectedRevision; restore needs commitId. Returns compact metadata unless source/preview requested.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
viewNocommits
limitNo
actionYes
cursorNo
previewNo
commitIdNo
includeSourceNo
expectedRevisionNo

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and destructiveHint=true, so safety is already flagged. The description adds the crucial nuance that undo/redo/restore are recorded 'as a new revision' rather than destroying the timeline, and that output is compact metadata unless source/preview is requested -- context an agent could not infer from the annotations alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three front-loaded sentences with no filler: purpose first, preconditions second, return behavior last. Dense but every clause carries information, so nothing feels wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter mutation tool with no output schema and near-zero schema coverage, the description covers the critical path but leaves several parameters and the commits-vs-backups distinction unexplained. It is adequate for a knowledgeable caller but not self-sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 11%, so the description carries heavy lifting. It usefully explains the roles of expectedRevision, commitId, and source/preview, but leaves view (commits vs backups), limit, cursor, and includeSource completely undocumented in both schema and description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific resource (drawing history) and enumerates the actual verbs -- list, undo, redo, restore -- plus the fact that changes are written as a new revision. This clearly separates it from siblings like get_drawing or update_drawing, which don't touch the revision timeline. It falls short of 5 only because the phrasing is compressed and assumes the reader already knows what a 'bounded local history' is.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives real prerequisites -- mutations require expectedRevision and restore needs commitId -- so the agent knows what each action demands. However, it never states when to choose this tool over alternatives (e.g., reading current state via get_drawing) or when-not to use it, leaving the routing implicit in the action enum.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

edit_creativeA
Destructive

Atomic typed creative edits with stable item IDs: update item fields, add/remove an item, or move_card to a column/index. Schedule dates and dependencies are validated. Mind-map additions retain existing branch positions; pins are respected. Use ordinary patch_drawing for local label/style changes.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
previewNo
operationsYes
includeSourceNo
expectedRevisionYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, so the safety profile is partly covered. The description adds real context beyond that: the edits are atomic, schedule dates and dependencies are validated, mind-map additions retain branch positions, and pins are respected. However it does not disclose concurrency/conflict behavior around expectedRevision or what happens on revision mismatch.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose and operation set, followed by validation and edge-case behavior, then the sibling routing. Sentences are dense and mostly earn their place, though fragments like 'pins are respected' are terse to the point of being cryptic.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation tool with no output schema and an untyped operations array, the description covers atomicity, validation, and edge behaviors reasonably well. But it omits the revision/concurrency semantics of the required expectedRevision and does not describe preview or includeSource, leaving meaningful gaps given the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 20% (just the 'name' parameter). The description clarifies the kinds of operations the untyped 'operations' array can carry, but the required 'expectedRevision' is never explained (no mention of optimistic concurrency or conflicts), and 'preview'/'includeSource' are wholly unaddressed. With low coverage the description fails to compensate for most parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (atomic typed creative edits with stable item IDs) and enumerates the actual operations it performs: update item fields, add/remove an item, move_card. It explicitly routes the agent to the sibling patch_drawing, so it is distinguishable from adjacent tools without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the alternative and the condition that selects it: 'Use ordinary patch_drawing for local label/style changes,' implying this tool is for structural edits. It gives the when-not clearly but does not disambiguate against other siblings like edit_drawing or compose_creative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

edit_drawingA
Destructive

Atomically edit nodes, connections, groups, pins, constraints, overlap permissions, patches or reflow. Example operations: pin api; insert_between df-edge-1 with redis; disconnect obsolete. Discover exact operation names/examples with get_capabilities. Returns compact metadata by default.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
previewNo
operationsYes
includeSourceNo
expectedRevisionYes

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the safety profile is covered. The description adds real behavioral context beyond that: edits are applied atomically, and the response is 'compact metadata by default' (implying includeSource expands it). It still leaves the concurrency contract around expectedRevision and the preview path unexplained.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tightly packed sentences, front-loaded with the core verb and object model, then examples, then the discovery pointer. No filler, though the enumerated operation examples are terse enough that they read as fragments rather than specifications.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, 5-parameter mutation tool with a required revision token and no output schema, the description covers the edit surface, atomicity, output shape hint and the get_capabilities escape hatch. It is still thin on the concurrency/prerequisite model and on preview/includeSource behavior, which an agent needs before calling it safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 20% (only 'name' is documented), so the description has to carry the load. It does add value by showing what operation entries look like ('pin api', 'insert_between df-edge-1 with redis') and redirecting to get_capabilities, but expectedRevision (a required optimistic-concurrency token), preview and includeSource remain semantically opaque in both places.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

It gives a specific verb ('edit') plus the object model it operates on (nodes, connections, groups, pins, constraints, overlap permissions, patches, reflow) and stresses atomicity, so an agent knows exactly what class of mutation this performs. It does not differentiate itself from close siblings like patch_drawing or update_drawing, which is the only reason it misses a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description points the agent at get_capabilities to discover exact operation names and examples, which is useful routing for operation syntax. But it never states when to use edit_drawing instead of patch_drawing or update_drawing, nor any preconditions such as needing the current revision, so usage is implied rather than specified.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_drawingC

Write SVG/PNG/JPG/WebP/vector PDF and return revision-specific paths. inline:false by default. Opt into inline:true for SVG text or a PNG preview; previewOptions controls the inline raster view without changing the exported file.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
formatNopng
inlineNo
stableNo
optionsNo
previewOptionsNo

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false, destructiveHint=false, so the agent already knows this is a non-destructive write. The description usefully clarifies that inline preview (and previewOptions) does not alter the exported file, which is genuine added context, but it says nothing about where files land, overwriting behavior, or auth requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences with the core action front-loaded and no filler. The shift from output formats to inline/previewOptions is slightly abrupt but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 6 parameters, two nested objects, no output schema, and near-zero schema coverage, the description is far too thin. It does mention revision-specific return paths, which helps fill the missing output schema, but leaves the options object, stable, and format semantics entirely unspecified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 17%, so the description bears most of the explanatory burden, yet it only touches inline and previewOptions. The stable flag, the entire options object (page, frame, scale, margin, metadata, textMode, landscape, background), and the format parameter receive no semantic explanation anywhere.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (write/export) and enumerates the resource formats (SVG/PNG/JPG/WebP/vector PDF) plus the returned artifact (revision-specific paths). It is clearly distinguishable from most siblings, but it never names or contrasts with the closest alternative, export_interchange.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the inline default and opt-in behavior, which is parameter-level guidance rather than tool-selection guidance. It gives no indication of when to export versus preview_drawing or export_interchange, nor any prerequisites for exporting.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_interchangeA

Write editable Mermaid, Excalidraw or draw.io handoff; return path and fidelity/loss report. embedNative:true explicitly embeds the full native model including hidden content. Default strict rejects losses. Source text returned only with inline:true. Original source stays unchanged.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
formatYes
inlineNo
optionsNo

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare write/non-destructive/non-open-world, and the description adds genuinely useful context beyond that: a fidelity/loss report is returned, strict policy rejects losses by default, and the original source stays unchanged. It stops short of describing failure modes or the exact loss-report shape.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded: the output artifact and its return values open the block, then option semantics follow. Semicolon-joined fragments carry a lot of meaning per word, though the run-on packing makes it slightly harder to scan than distinct sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description usefully names the return values (path plus fidelity/loss report) and the non-mutation guarantee for a write tool. The main gap is the unexplained scope/geometry options inside the nested options object, which the schema's 25% coverage does not fill.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 25%, so the description must compensate. It does explain embedNative and inline and clarifies the strict default for options.policy, but the scope and geometry enums are left undefined and format semantics are unaddressed beyond the enum list.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Write) and resource (editable Mermaid/Excalidraw/draw.io handoff), so the purpose is immediately clear and distinguishable from an image-oriented export. However, it never names or contrasts with the sibling export_drawing, leaving the agent to infer the split between the two.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives operating guidance (embedNative for full native model, default strict rejects losses, inline controls source text) which implies when certain options matter, but it never states when to choose this tool over export_drawing or preview_drawing. Usage is implied rather than explicitly framed as a decision rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_capabilitiesB
Read-only

Discover supported templates, primitives/roles, styles, operations or concrete workflow examples without fetching full schemas. Start with overview.

ParametersJSON Schema
NameRequiredDescriptionDefault
topicNooverview
recipeNo

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds a useful trait — it returns capability info "without fetching full schemas" — but says nothing about the shape of results, relative cost, or how the recipe parameter alters behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two efficient sentences with no filler, and the primary purpose leads. It is dense and front-loaded, though the topic enumeration and the trailing "Start with overview" hint sit in a slightly awkward order.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and 0% parameter description coverage, the description bears the full load for a tool with ten enum topics plus an unexplained recipe parameter, and it falls short. An agent still cannot tell what each topic returns or what recipe does.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry parameter meaning, and it only partially does. It names some topic values (templates, styles, operations, examples) but omits symbols, projects, technical, interchange, and creative, invents "primitives/roles" which is not an enum value, and leaves the recipe parameter entirely unexplained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb (Discover) and enumerates the resource categories it exposes (templates, primitives/roles, styles, operations, workflow examples), so the agent knows this is a capability-introspection tool. However, it does not distinguish itself from siblings that share surface area, notably list_templates and get_format, leaving overlap unresolved.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Start with overview" gives a weak sequencing hint about which topic to begin with, which is implied usage guidance. There is no statement of when to prefer this tool over list_templates/get_format, no prerequisites, and no exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_drawingA
Read-only

Default: a compact document and graph summary. Use view elements with ids to read selected elements and semantic associations; view graph pages semantic records and incident connections. view source explicitly returns complete JSON. Cursors are source/query-bound.

ParametersJSON Schema
NameRequiredDescriptionDefault
idsNo
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
viewNosummary
limitNo
cursorNo

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already state readOnlyHint and openWorldHint=false. Beyond that, the description adds meaningful behavior: the default is compact, source returns complete JSON, and cursors are source/query-bound. It still omits details like response format for default summary or limit behavior, but it adds useful context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short and front-loads the default behavior. The view-specific guidance is compressed but mostly clear, with only minor awkwardness in the fragmented sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 5-parameter read tool with no output schema and many siblings, the description covers most view outputs and cursor semantics. However, it omits the description view, limit behavior, and guidance on when this tool is preferable to list_drawings, preview_drawing, or check_drawing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is low at 20%, so the description must compensate. It clarifies the view modes, how ids pair with elements, and cursor binding, but it does not explain limit, and the description view in the enum is not covered at all.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description implies retrieval of drawing content by stating the default output is a compact document and graph summary, and it differentiates the available view modes. It does not explicitly distinguish itself from siblings such as list_drawings, preview_drawing, or check_drawing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives view-level guidance, e.g. use view elements with ids to read selected elements and view graph for semantic records and connections. However, it gives no tool-level when-to-use guidance versus alternatives, no exclusions, and no prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_formatA
Read-only

Explicitly retrieve full native schemas and a source example. For concise discovery prefer get_capabilities.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations establish readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds the material behavioral fact that this returns expanded schemas plus a concrete source example, which tells the agent about payload weight versus get_capabilities.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with no filler, and the primary action is front-loaded ahead of the alternative-routing clause.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no parameters and no output schema, the description bears the burden of describing the return, and it does so at a high level (full native schemas + source example). It stops short of noting scale or structure, but nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is no schema semantics to clarify; the default baseline of 4 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: retrieving full native schemas plus a source example. It also distinguishes itself from the sibling get_capabilities, though the ambiguous name 'get_format' (format of what?) leaves the resource slightly under-specified.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: use get_capabilities for concise discovery, and this tool when you need the full/explicit schema plus an example. Clear selection context, though it doesn't state what happens if no format exists or any prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

import_drawingA
Destructive

Import Mermaid flowchart/sequence/ER, Excalidraw JSON or single-page draw.io XML. Discover drawfather://interchange first. Strict conversion blocks unsupported content; preserve explicitly accepts reported losses and keeps exact original input. Native snapshots merge supported edits or report conflicts. dryRun validates without writing. Existing files require expectedRevision.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
dryRunNo
formatYes
sourceYes
optionsNo
previewNo
includeSourceNo
expectedRevisionNo

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag this as a destructive write (destructiveHint=true), and the description adds real behavior: strict-vs-preserve conversion semantics, native snapshot merge/conflict reporting, dryRun as a non-writing validation mode, and a revision precondition for existing files. It does not say what happens to an existing file's prior contents on overwrite or what the call returns, so it is not fully transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Roughly six terse sentences, front-loaded with what can be imported, and each sentence carries distinct information about policy, merging, validation, and revision. The telegraphic style and the mid-description 'Discover drawfather://interchange first' aside reduce readability slightly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter destructive write with no output schema, the description covers conversion policy, conflict handling, and concurrency but never says what the import returns or how preview/includeSource results are surfaced. Combined with the low schema coverage, an agent can call it but cannot fully predict output or the semantics of several parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 13% (basically just `name`), so the description must compensate and it only partially does: it clarifies the `format` enum values, `dryRun`, `options.policy` (strict/preserve), and `expectedRevision`. It leaves the large nested `preview` object (ids/crop/width/height/background) and `options.scope`, `options.geometry`, `options.embedNative`, and `includeSource` completely unexplained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence gives a specific verb (Import) plus the exact accepted source formats (Mermaid flowchart/sequence/ER, Excalidraw JSON, single-page draw.io XML), which separates it from the compose_* and edit_* siblings by verb and input domain. It stops short of naming an alternative tool for a given scenario, so sibling differentiation is implied rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives conditional guidance: strict blocks unsupported content vs preserve accepts reported losses, dryRun validates without writing, and existing files require expectedRevision. It also directs the agent to discover drawfather://interchange first. No explicit statement of when to import versus compose/create from scratch, which is the main gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_drawingsB
Read-only

List saved drawing names with pagination.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
cursorNo

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, covering the safety profile. The description adds only the pagination trait, with no detail on cursor semantics, ordering, or limits, so it contributes modestly beyond structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with zero filler. The core action and scope are stated immediately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

A simple read-list tool with annotations covering safety and no output schema need not explain returns, but the paging contract (cursor source, ordering, empty results) is absent, leaving a gap an agent would hit on first use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Both parameters have 0% schema description coverage, so the description must compensate. Saying 'with pagination' gestures at limit/cursor but gives no meaning for either (page size bounds, cursor opacity), leaving the parameters effectively undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb (List) and resource (saved drawing names) and adds scope (with pagination). It does not distinguish itself from siblings like get_drawing or list_templates, but the operation is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this versus alternatives such as get_drawing or drawing_history. Nothing states preconditions or when-not to call it, leaving the agent to infer from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_templatesB
Read-only

Get general composition examples, the typed technical catalog and sketch styles. Request get_capabilities topic technical with recipe for a complete technical design.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds content-type context (what categories of templates exist), but says nothing about return format, size, or pagination for a list-style tool, so it adds only moderate value over the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with the returned content front-loaded and the redirect to get_capabilities trailing. Nothing is padded, though the first sentence is a comma-spliced list that is slightly ambiguous about whether these are three distinct item types.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the burden of describing return values, and it does sketch three content categories. It stops short of clarifying the shape/format of those results or how they relate to the compose_* tools, leaving moderate gaps for a zero-param catalog tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so per the baseline this dimension defaults to 4. There is no argument syntax for the description to clarify or obscure.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The verb 'Get' is vague, but the description enumerates three concrete things returned (composition examples, typed technical catalog, sketch styles). It never uses the word 'templates' from the tool name, so the mapping between name and content is left for the agent to infer, and it does not distinguish itself from list_drawings or the compose_* siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The second sentence routes the agent to get_capabilities (topic technical, recipe) for a complete technical design, which is useful explicit guidance. However, it gives no condition for when to prefer list_templates over the compose_* or get_format siblings, so usage is only partially implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

migrate_drawingA

Upgrade v1 to v2 with an exact-byte backup and unchanged appearance. Already-v2 migration is a revision-checked no-op. Source and preview are opt-in.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
previewNo
includeSourceNo
expectedRevisionYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare it is a non-read-only, non-destructive, closed-world mutation. The description adds real behavioral context: an exact-byte backup is created, appearance is preserved, and re-running on an already-v2 drawing is a revision-checked no-op. It is consistent with destructiveHint=false (backup + no-op) and readOnlyHint=false. It stops short of describing failure behavior on a revision mismatch.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core action, no filler. The safety-relevant clause (backup, unchanged appearance) appears before the no-op and opt-in details, which is appropriate ordering.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with 4 parameters, 25% schema coverage, a nested preview object, and no output schema, the description covers the headline behaviors but leaves gaps: name handling, expectedRevision mismatch consequences, and what the migration returns are all absent. Adequate but not complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 25%, so the description should compensate. It lights up includeSource and preview ('opt-in') and hints at expectedRevision via 'revision-checked', but gives no semantic detail for the required 'name' parameter (the schema description carries that) and no explanation of what a revision check failure means. Partial compensation for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Upgrade v1 to v2', and adds the exact-byte backup and unchanged-appearance outcome. An agent can tell this is a format-migration tool. However, it never names or distinguishes itself from adjacent siblings like update_drawing, patch_drawing, or repair_drawing, leaving the boundary implicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Already-v2 migration is a revision-checked no-op' and 'Source and preview are opt-in' imply when this tool is appropriate and how to toggle optional behavior, but there is no explicit when-to-use / when-not-to-use guidance and no named alternative for cases where migration isn't the right operation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

patch_drawingA
Destructive

Patch labels, node detail or partial styles by ID without resending geometry. Example patches:[{id:"api",label:"Core API",style:{fill:"#d3e1f5"}}]. Read the selected element first and pass expectedRevision. seed/sketch:null inherit document values; style owned labels using their labelId.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
patchesYes
previewNo
includeSourceNo
expectedRevisionYes

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and readOnlyHint=false; the description adds real behavioral context beyond that: partial patch semantics (no geometry resend), optimistic concurrency via expectedRevision, and null inheriting document values. It stops short of stating exactly what gets overwritten or how conflicts are reported.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core purpose, then the example, then the precondition, then the inheritance caveat. Dense but every sentence carries information; only the inline example is slightly verbose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

A destructive mutation tool with 5 params at 20% coverage and no output schema needs more. The description covers the critical read-then-patch workflow and patch field semantics, but leaves preview/includeSource unexplained and does not describe the failure mode when expectedRevision mismatches.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 20%, and the description partially compensates: it shows a patch example, explains seed/sketch null inheritance, and notes label ownership via labelId. However, preview, includeSource, and the concurrency meaning of expectedRevision are not meaningfully explained, leaving gaps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Patch) and specific resources (labels, node detail, partial styles) by ID, plus the key differentiator 'without resending geometry'. It clearly conveys a partial-update operation, though it never names update_drawing/edit_drawing as the alternative for full edits.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a workflow precondition ('Read the selected element first and pass expectedRevision') and null-inheritance semantics, which is useful implied guidance. But it never states when to prefer this over update_drawing or edit_drawing, so the choice among siblings is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

preview_drawingA
Read-only

Read-only PNG preview: set width/height, an absolute crop or selected ids, padding, background and scaleUp. ID selection crops the region including nearby context; it does not edit or export source.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
optionsNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description still adds real context: 'ID selection crops the region including nearby context' and 'does not edit or export source' tell the agent how the crop behaves and that source is untouched, which is beyond what the annotations convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with the core fact ('Read-only PNG preview') front-loaded, followed by the option inventory and the two behavioral caveats. No filler or restatement of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, but the description names the return format (PNG) and covers the nested options object, so an agent can call it correctly. Minor gaps remain around the required 'name' parameter and dimensions of the returned image, but nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 50% and the nested 'options' properties carry no descriptions, so the description does real work by enumerating width/height, absolute crop, ids, padding, background and scaleUp. It also adds meaning the schema lacks ('absolute crop', id-selection includes nearby context), though it omits any note on the required 'name' stem.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and output ('Read-only PNG preview') of a drawing, so an agent immediately knows it produces an image rather than mutating data. It does not, however, name or contrast itself with the sibling it is most likely confused with, export_drawing, leaving sibling differentiation to inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The clause 'it does not edit or export source' implicitly signals when this is preferred over edit_drawing/export_drawing, but it never states the positive condition for choosing preview or any prerequisites. Usage is implied rather than spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

project_diagramsB
Destructive

Maintain repository diagrams using a project manifest. Check/validate freshness, render stable/revisioned files and optional managed docs, list affected drawings from changed paths/Git base, produce semantic/visual diff artifacts, or acknowledge inspected source relationships at exact hashes. Rendering never acknowledges code accuracy. Paths stay inside the manifest directory. metadata export settings explicitly disclose references/source; default none.

ParametersJSON Schema
NameRequiredDescriptionDefault
idsNo
baseNo
limitNo
actionYes
cursorNo
manifestNodrawfather.project.json
directoryNo
writeDocsNo
sourceHashNo
changedFilesNo
referenceHashNo

TDQS

B3.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and readOnlyHint=false, so the safety profile is already carried. The description nonetheless adds genuinely non-obvious behavioral facts: the render/acknowledge separation ("Rendering never acknowledges code accuracy"), hash-bound acknowledgment semantics, the path confinement rule, and the disclosure default for metadata export. The notable gap is that it never explains which action is destructive or what data can be lost.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded in the first sentence and every later sentence carries constraints, but the long comma-spliced action list ("Check/validate... render... list... produce... or acknowledge...") is dense and hard to parse, mixing action enumeration with the rules that apply to those actions.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter, seven-action, destructive tool with no output schema, the description covers a lot of ground but omits the info action entirely, never maps the enum values to their parameters, and leaves the destructive behavior and its scope unspecified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 11 parameters, so the description must compensate. It does add implicit meaning for several ("project manifest" → manifest, "Git base" → base, "changed paths" → changedFiles, "exact hashes" → sourceHash/referenceHash, "optional managed docs" → writeDocs), but leaves ids, limit, and cursor entirely unexplained, so compensation is only partial.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence gives a specific verb+resource ("Maintain repository diagrams using a project manifest") and the following clauses enumerate the seven action verbs, which separates it from the drawing-level siblings (create_drawing, edit_drawing, check_drawing) by operating at the manifest/repository scope. However, the multi-action nature means the agent still cannot tell which behavior maps to which enum value, and the "info" action is never described at all.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The action listing implies usage ("Check/validate freshness", "list affected drawings from changed paths/Git base") and gives constraints ("Paths stay inside the manifest directory", rendering never acknowledges accuracy), but there is no explicit statement of when to prefer this tool over siblings like check_drawing or preview_drawing, nor any when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

repair_drawingA
Destructive

Preview bounded repair, then apply the returned planId with identical options and expectedRevision. Default report is compact; detail:full requests all findings/attempts. includeSource and preview are independent opt-ins. Remaining errors block writes.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
actionNopreview
checksNo
detailNocompact
planIdNo
previewNo
repairsNo
maxPassesNo
includeSourceNo
expectedRevisionYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool destructive and non-read-only; the description adds real context beyond them - the plan/preview-then-apply protocol, the revision guard, full-vs-compact reporting, and that remaining errors block writes. It stops short of stating what content a repair mutates or what permissions are needed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense, front-loaded sentences with no filler; the workflow leads and details follow. A few phrases ('independent opt-ins') are terse to the point of being cryptic, but overall the structure is efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter tool with nested objects and no output schema, the description covers the workflow and error-blocking well but leaves much of the parameter surface and the response shape unexplained (only implicitly noting a returned planId). Adequate but with clear gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 10%, so the description carries the burden, and it does clarify planId, expectedRevision, detail levels, includeSource, and preview. But it says nothing about checks, repairs, maxPasses, or action, leaving the majority of this 10-parameter tool's semantics undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description conveys a clear two-phase purpose: preview a bounded repair, then apply the returned planId. The verb/resource is understandable from context, but it never distinguishes itself from likely neighbors such as check_drawing, preview_drawing, or patch_drawing, so an agent must infer the boundary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a concrete workflow (preview first, then apply with the returned planId and identical options/expectedRevision) and a key constraint ('Remaining errors block writes'). However, it never names or excludes alternative sibling tools, so the when-to-use-this-vs-that question is answered only implicitly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_presentationB
Destructive

Embed local fonts and image/SVG assets into a saved drawing, or update brand, fallback, description and text mode. All paths are read locally; no URL fetching. Assets attach to existing rectangle IDs. Font embedding requires its license/permission description. Native source retains bytes for clean-machine exports.

ParametersJSON Schema
NameRequiredDescriptionDefault
fontNo
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
assetsNo
previewNo
presentationNo
includeSourceNo
expectedRevisionYes

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The destructiveHint annotation already flags this as a mutation, but the description adds meaningful non-obvious behavior: all paths are read locally with no URL fetching, assets bind to existing rectangle IDs, font embedding requires a license, and native source is retained for clean-machine exports. It omits the optimistic-concurrency implication of expectedRevision and does not state what gets overwritten, but it comfortably exceeds the annotation baseline.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, front-loaded with the primary action, then constraints and gotchas. Dense but each sentence carries information; no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation tool with seven parameters, nested objects, no output schema, and low schema coverage, the description should cover more. It handles the asset/font path semantics well but leaves revision-conflict behavior, the free-form presentation object, preview, and the concrete consequences of the destructive flag unexplained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 14%, so the description must compensate, and it partially does: it clarifies font.license purpose, that assets.path is read locally and attaches via existing rectangle IDs, and the intent of includeSource. It says nothing about name, expectedRevision, presentation, or preview, leaving several of the seven parameters unexplained in both schema and prose.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names specific operations (embed fonts/assets, update brand/fallback/description/text mode) and a clear resource scope, so the agent knows this modifies an existing drawing's presentation layer. It does not, however, differentiate itself from siblings like update_drawing, patch_drawing, or edit_drawing, leaving the agent to infer the boundary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit when-to-use or when-not-to-use guidance, and no alternatives are named among the many sibling tools that also mutate drawings. The path/font licensing notes imply context but do not route the agent between set_presentation and its siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_drawingA
Destructive

Low-level complete-element upserts, removes, or document changes. Fetch get_format for full element fields; the engine validates them before writing. Prefer patch_drawing for small label/style changes. Source and preview are opt-in.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesExact drawing file stem, without the .drawfather extension. Preserve the user-requested name; this is separate from design.title.
seedNo
titleNo
canvasNo
removeNo
sketchNo
upsertNo
previewNo
includeSourceNo
expectedRevisionYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false and destructiveHint=true, so the destructive character is known; the description adds that the engine validates input before writing and that source/preview are opt-in. However, it never explains what remove/upsert actually overwrite, nor the optimistic-concurrency meaning of the required expectedRevision, so it adds only partial behavioral context on top of annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, front-loaded with what the tool does before moving to prerequisites and alternatives. Dense and mostly waste-free, though "Low-level complete-element upserts, removes, or document changes" crams several distinct operations into one clause.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter, nested, destructive write tool with no output schema and 10% schema coverage, the description covers the alternative and validation but omits the semantics of expectedRevision, what the return looks like, and how revision conflicts are signaled. Adequate for routing, incomplete for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 10% across 10 parameters, so the description carries real weight and does help by pointing to get_format for the opaque, untyped upsert element fields. But it adds nothing about the required expectedRevision (a concurrency token), name, seed, sketch, or canvas, leaving most parameters undocumented in both places.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action family – "complete-element upserts, removes, or document changes" – for the update_drawing tool, and differentiates its low-level, complete-element scope from patch_drawing. It stops short of plainly saying it mutates a drawing document, but the verb/resource pair is inferable and the scope note distinguishes it from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Prefer patch_drawing for small label/style changes" gives explicit alternative routing with a selection condition, and "Fetch get_format for full element fields" tells the agent what to do before calling. It doesn't address the other write siblings (edit_drawing, compose_drawing) or state prerequisites for expectedRevision, so it's clear context but not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 23 tool updatesv0.1.0
    • First observedcheck_drawing
    • First observedcompose_creative
    • First observedcompose_drawing
    • First observedcompose_technical
    • First observedcreate_drawing
    • First observeddrawing_history
    • First observededit_creative
    • First observededit_drawing
    • First observedexport_drawing
    • First observedexport_interchange
    • First observedget_capabilities
    • First observedget_drawing
    • First observedget_format
    • First observedimport_drawing
    • First observedlist_drawings
    • First observedlist_templates
    • First observedmigrate_drawing
    • First observedpatch_drawing
    • First observedpreview_drawing
    • First observedproject_diagrams
    • First observedrepair_drawing
    • First observedset_presentation
    • First observedupdate_drawing

TDQS

B3.4/5.0

Scored across 23 tools

Disambiguation3/5

The four edit-style tools (edit_drawing, update_drawing, patch_drawing, edit_creative) overlap significantly; descriptions do attempt to differentiate them (patch for small label/style, update for full element upserts, edit for atomic operations), which helps but still requires careful reading. The three compose_* tools are separable by diagram domain, and check/repair/preview/export are distinct. Overall boundaries exist but are blurry in the mutation cluster.

Naming Consistency4/5

Most tools follow a predictable snake_case verb_noun pattern (compose_*, create_drawing, edit_*, get_*, list_*, import_drawing, export_*, preview_drawing, check_drawing, repair_drawing, migrate_drawing). A few deviate: 'project_diagrams' (noun_verb) and 'drawing_history' (noun_noun), which break the pattern slightly. Still readable and largely consistent.

Tool Count3/5

23 tools is on the heavy side for the stated scope; several (compose_drawing, compose_technical, compose_creative and the four editors) suggest consolidation is possible. It is defensible given the breadth of diagram types, interchange formats, and repair/history workflows, but it sits in the heavy band rather than a tight, well-scoped set.

Completeness4/5

Coverage is broad: create, read, edit, patch, import, export, preview, check, repair, migrate, history, and project management are all present, which is strong lifecycle coverage for a diagramming engine. However there is no explicit delete/rename tool for drawings, a minor gap an agent would have to work around via history or overwrite.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers