# Sketchdex (npm · sketchdex)

An MCP server that lets AI agents draw hand-drawn Excalidraw diagrams as files on your machine.

- Trust score: 78/100 (medium)
- Change this week: +3
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-09-25

## Components

- npm · `sketchdex`: 78/100 (this document), [markdown](https://verifymcp.io/servers/lucasr1b-sketchdex/sketchdex.md), [page](https://verifymcp.io/servers/lucasr1b-sketchdex/sketchdex)

## Channel facts

- Registry: `npm`
- Package: `sketchdex`
- Version: `0.1.2`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-09-25.

- **Supply Chain Security**: 98/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - No install/post-install scripts declared.
  - 31 of 95 dependencies flagged as unhealthy.
- **Provenance & Transparency**: 45/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 20 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 78/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 5659 tokens (~217/item across 26 items; 19 tools + 7 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 70/100
  - Stability observed for 21 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 95/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 85% of tool parameters carry a description.
- **Tool Safety**: 75/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - 0 of 1 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "delete_elements" implies "delete" and declares no destructiveHint at all, which the MCP spec reads as destructive by default.
  - An AI judge read all 21 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### How do I install the Sketchdex MCP server?

Sketchdex runs locally as an npm package, launched with npx -y sketchdex. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add lucasr1b-sketchdex -- npx -y sketchdex
```

### Cursor

```json
{
  "mcpServers": {
    "lucasr1b-sketchdex": {
      "command": "npx",
      "args": [
        "-y",
        "sketchdex"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "lucasr1b-sketchdex": {
      "command": "npx",
      "args": [
        "-y",
        "sketchdex"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add lucasr1b-sketchdex -- npx -y sketchdex
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "lucasr1b-sketchdex": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "sketchdex"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add lucasr1b-sketchdex --command npx --arg -y --arg sketchdex
```

### Hermes

```yaml
mcp_servers:
  lucasr1b-sketchdex:
    command: "npx"
    args: ["-y", "sketchdex"]
```

### Netclaw

```json
{
  "McpServers": {
    "lucasr1b-sketchdex": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "sketchdex"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add lucasr1b-sketchdex -t stdio -c npx -a -y sketchdex
```

### Other

```json
{
  "mcpServers": {
    "lucasr1b-sketchdex": {
      "command": "npx",
      "args": [
        "-y",
        "sketchdex"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-09-25 (score 78, 0)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-09-24 (score 78, +1)

No change was recorded against any check on this day. Stability & Change Management went from 63 to 67. That category is still filling its 30-day observation window: 19 days of observed history at the previous scan, 20 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-21 (score 77, +1)

No change was recorded against any check on this day. Stability & Change Management went from 53 to 57. That category is still filling its 30-day observation window: 16 days of observed history at the previous scan, 17 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-19 (score 76, +1)

No change was recorded against any check on this day. Stability & Change Management went from 47 to 50. That category is still filling its 30-day observation window: 14 days of observed history at the previous scan, 15 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-17 (score 75, +1)

No change was recorded against any check on this day. Stability & Change Management went from 40 to 43. That category is still filling its 30-day observation window: 12 days of observed history at the previous scan, 13 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-15 (score 74, +1)

No change was recorded against any check on this day. Stability & Change Management went from 33 to 37. That category is still filling its 30-day observation window: 10 days of observed history at the previous scan, 11 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-13 (score 73, +1)

No change was recorded against any check on this day. Stability & Change Management went from 27 to 30. That category is still filling its 30-day observation window: 8 days of observed history at the previous scan, 9 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-12 (score 72, +3)

- [functional improvement] Stability: unverified → 0.27

## MCP tools (19)

### `list_scenes` (~31 tokens)

Every scene in the vault with its id, name, element count and last-edited time. Start here.

### `describe_scene` (~113 tokens)

What is on a scene, as structure rather than pixels: counts by type, overall bounds, and a rounded summary of each element with its id, position, size, text and bindings. Cheaper than read_scene and usually enough to plan an edit.

Input parameters:

- `limit` (number): Max elements to list (default 400).
- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.
- `type` (string): Only elements of this type.

### `read_elements` (~116 tokens)

Full, unabridged elements, filtered down to the ones you need. Use this rather than read_scene when editing a few things in a busy scene.

Input parameters:

- `contains` (string): Only elements whose text contains this.
- `ids` (array)
- `limit` (number): Default 100.
- `region` (object): Only elements overlapping this box.
- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.
- `type` (string)

### `read_scene` (~123 tokens)

The whole scene exactly as stored, plus the path to the .excalidraw file on disk. Large scenes run to thousands of elements, so prefer describe_scene or read_elements unless you genuinely need everything. The path is there for edits no tool here covers - take a snapshot first if you use it.

Input parameters:

- `includeFiles` (boolean): Include the embedded image map. Off by default: it is base64 and usually megabytes.
- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.

### `create_scene` (~761 tokens)

Make a new scene, optionally with its starting elements.

Input parameters:

- `elements` (array): Excalidraw elements. Any field of a real element is honoured verbatim; what you omit gets a valid default (id, index, seed, version are generated). USE THIS FOR diagrams, layout, text, boxes, arrows…
- `name` (string)

### `add_elements` (~842 tokens)

Append elements to a scene, leaving everything already there untouched. The usual way to draw something new.

Input parameters:

- `elements` (array, required): Excalidraw elements. Any field of a real element is honoured verbatim; what you omit gets a valid default (id, index, seed, version are generated). USE THIS FOR diagrams, layout, text, boxes, arrows…
- `label` (string, required): Short description of what this change is doing, e.g. 'add the dog illustration'. Shown next to the snapshot in the history sidebar, which is how the user decides whether to keep or revert it. Always…
- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.

### `update_elements` (~183 tokens)

Change named fields on existing elements. Send only what changes - {id, x: 40} moves one box and leaves its other 25 fields alone. Pass a list in `elements`, each carrying its `id`, or use `ids` + `patch` to apply one change across many.

Input parameters:

- `elements` (array): Partial elements, each with an `id` and the fields to change.
- `ids` (array)
- `label` (string, required): Short description of what this change is doing, e.g. 'add the dog illustration'. Shown next to the snapshot in the history sidebar, which is how the user decides whether to keep or revert it. Always…
- `patch` (object)
- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.

### `delete_elements` (~99 tokens)

Remove elements by id.

Input parameters:

- `ids` (array, required)
- `label` (string, required): Short description of what this change is doing, e.g. 'add the dog illustration'. Shown next to the snapshot in the history sidebar, which is how the user decides whether to keep or revert it. Always…
- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.

### `move_elements` (~222 tokens)

Shift a set of elements by dx, dy in one write, keeping everything else about them. Select by ids, groupIds (an import_svg piece), a region box, or any mix. A container's label always moves with it, and an arrow bound to something that moves keeps that end attached (include the arrow itself to move it whole). Returns the new bounds of what moved.

Input parameters:

- `dx` (number): Scene px to the right (negative = left).
- `dy` (number): Scene px down (negative = up).
- `groupIds` (array)
- `ids` (array)
- `label` (string, required): Short description of what this change is doing, e.g. 'add the dog illustration'. Shown next to the snapshot in the history sidebar, which is how the user decides whether to keep or revert it. Always…
- `region` (object): Everything overlapping this box moves.
- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.

### `replace_scene` (~859 tokens)

Replace a scene's entire contents. Destructive by design - the previous state is snapshotted, but prefer add_elements or update_elements when you only mean to change part of it.

Input parameters:

- `elements` (array, required): Excalidraw elements. Any field of a real element is honoured verbatim; what you omit gets a valid default (id, index, seed, version are generated). USE THIS FOR diagrams, layout, text, boxes, arrows…
- `label` (string, required): Short description of what this change is doing, e.g. 'add the dog illustration'. Shown next to the snapshot in the history sidebar, which is how the user decides whether to keep or revert it. Always…
- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.

### `set_background` (~166 tokens)

Set the paper: the scene's real background colour, shown exactly as given (never inverted). The default pen for hand drawing follows it, so the next stroke in the app is visible. Elements already drawn keep their colours - recolour their ink yourself if you flip a scene from light to dark or back. New scenes start on dark paper (#121212).

Input parameters:

- `color` (string, required)
- `label` (string, required): Short description of what this change is doing, e.g. 'add the dog illustration'. Shown next to the snapshot in the history sidebar, which is how the user decides whether to keep or revert it. Always…
- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.

### `render_scene` (~346 tokens)

A PNG of the scene as it actually renders, so you can look at what you drew. Use it to check your own work - proportions, overlaps, whether the thing reads as the thing. Always written to a file as well as returned. A tall or wide page (long edge more than about twice the short one, and too big to fit at the asked size) comes back as a few tiles cut along its length, each with the scene box it shows, so a whole board is readable in one call; a `region` renders just that box, which is the way to look closely at one part. When an image is too big to travel inline you get a downscaled preview plus the file path.

Input parameters:

- `ids` (array): Render only these elements.
- `maxWidth` (number): Cap the long edge in pixels. Default 1400. Above ~1200 the result is a file path instead of an inline image.
- `region` (object): Render only what overlaps this box, in scene coordinates. Take the numbers from describe_scene's `bounds`.
- `scale` (number): Pixel density, 1-3. Default 1.
- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.
- `tiles` (number): Split the picture into this many tiles along its long axis (max 8). Default: chosen from the shape of the scene, 1 for anything roughly square. Pass 1 to force a single image.
- `transparent` (boolean): Leave the paper out of the PNG (alpha background). For dropping a sketch onto a slide or a page.

### `import_svg` (~878 tokens)

Draw by writing SVG. THE way to draw anything that has to look like
something: a character, creature, object, vehicle, logo, illustration.
This is what produces good figures; stacking shapes with add_elements does
not.

The result is hand-drawn, not pasted: every path becomes a real editable
Excalidraw element (grouped as one piece), curves are re-spaced to
hand-sized strokes and drawn with the sketchy pen, <circle>/<ellipse>/<rect>
become native shapes. Write the SVG for SHAPE, PROPORTION and COLOUR and let
the canvas supply the pen - do not fake wobble or hatching in the SVG.

A recipe that works for a figure:
  \* viewBox about 300 x 600 for a standing figure; import at width 350-450.
  \* ONE closed path per body region - torso, each leg, each arm - tapered
    like a real limb (forearm ~60% of the upper arm, calf into a narrow
    ankle), plus head, hands, feet. Let them overlap; later paths draw on
    top. Then detail as separate strokes OVER the silhouette: plates, seams,
    webbing, a knee line. A few, not many.
  \* Every shape: fill=<vibrant, character-accurate hex> stroke=<the scene
    ink from describe_scene, or a deep shade of the fill> stroke-width 2 to
    2.5. Filled shapes with no stroke read as flat.
  \* Flat colour, no shading. One solid fill per part; a darker part is a
    darker hex, not a hatched overlay or a shadow shape. The sketchy
    outline carries the drawing - texture on top of it looks overworked.
  \* Proportion from a rule: 7-8 heads tall for heroic, 5-6 for stylised.
    Head first, derive the rest.
  \* Then render_scene and LOOK; fix what is off. The first pass is usually
    mis-proportioned, the second is right.

Supported: path (all commands), rect, circle, ellipse, line, polyline,
polygon, g, transform, <style>/class, <use>/<defs>, presentation attributes,
text. viewBox honoured exactly. Gradients flatten to their first stop; pass
holeColor to punch compound-path holes.

Input parameters:

- `fillStyle` (string): Fill for every filled shape. Default solid. hachure for a lighter, sketchier piece (small shapes stay solid); cross-hatch for weight.
- `group` (boolean): Group the result as one unit. Default true.
- `height` (number): Optional bound on height.
- `holeColor` (string): Backdrop colour used to punch compound-path holes.
- `label` (string, required): Short description of what this change is doing, e.g. 'add the dog illustration'. Shown next to the snapshot in the history sidebar, which is how the user decides whether to keep or revert it. Always…
- `roughness` (number): 0 precise, 1 sketchy (default in sketch mode), 2 very sketchy.
- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.
- `step` (number): Anchor spacing for curves in sketch mode, in canvas px. Default 18. Lower keeps more of the source curve; higher is looser.
- `style` (string): sketch (default): hand-drawn treatment - anchors re-spaced, curves as curves, roughness 1, native circles/rects. precise: every flattened vertex kept, roughness 0 - for a logo or a drawing that must…
- `svg` (string, required): Complete SVG markup, including the <svg> element and its viewBox.
- `tolerance` (number): Curve flattening, in source units. Default 3. Lower is smoother and heavier.
- `width` (number): Scale the artwork to this width, keeping its aspect ratio. Height follows.
- `x` (number): Where to place it on the canvas. Default 0.
- `y` (number): Default 0.

### `check_scene` (~146 tokens)

Find layout problems by geometry instead of by looking: text hidden behind a filled shape drawn after it, captions running past the panel they sit in, labels too tall for their container, zero-size elements, broken arrow bindings, strays parked far off, exact duplicates. Each finding carries the element ids, so the fix is one update_elements call. Run it after a batch of drawing - it is far cheaper than a render and catches what a render would only show you if you looked closely.

Input parameters:

- `limit` (number): Max findings (default 60).
- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.

### `sketchdex_info` (~50 tokens)

Version of this server, where it is running from, which vault it is using, and how long this process has been alive. Use it to confirm you are talking to the build you think you are.

### `sketchdex_docs` (~106 tokens)

The manual, for answering the user's questions and fixing problems without guessing: install on any client, where scenes are stored and how to move the vault, the library app, what rendering needs, every tool, the drawing contract, and troubleshooting for the errors that come up. No topic returns the index.

Input parameters:

- `topic` (string): One of: install, vault, app, rendering, tools, drawing, troubleshooting. Omit for the index; `all` for the whole manual.

### `snapshot_scene` (~133 tokens)

Stash the current state without changing anything, so it can be restored from the history sidebar. Do this before editing a .excalidraw file directly with your own file tools - every other tool here snapshots on its own.

Input parameters:

- `label` (string, required): Short description of what this change is doing, e.g. 'add the dog illustration'. Shown next to the snapshot in the history sidebar, which is how the user decides whether to keep or revert it. Always…
- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.

### `list_history` (~45 tokens)

Snapshots held for a scene, newest first.

Input parameters:

- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.

### `restore_snapshot` (~64 tokens)

Put a snapshot back on the canvas. This is itself snapshotted, so reverting a revert is possible.

Input parameters:

- `scene` (string, required): Scene id, exact name, or a unique part of the name. Use list_scenes if unsure.
- `snapshot` (string, required)

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/lucasr1b-sketchdex/sketchdex#diagnostics

## Score history

- 2026-09-25: 78
- 2026-09-24: 78
- 2026-09-23: 77
- 2026-09-22: 77
- 2026-09-21: 77
- 2026-09-20: 76
- 2026-09-19: 76
- 2026-09-18: 75
- 2026-09-17: 75
- 2026-09-16: 74
- 2026-09-15: 74
- 2026-09-14: 73
- 2026-09-13: 73
- 2026-09-12: 72
- 2026-09-11: 69
- 2026-09-10: 69
- 2026-09-09: 69
- 2026-09-08: 69
- 2026-09-07: 69
- 2026-09-06: 69
- 2026-09-05: 69
- 2026-09-04: 54

## Common questions

### What is the Sketchdex MCP server?

Sketchdex is an MCP server listed in the public MCP registry as io.github.lucasr1b/sketchdex. An MCP server that lets AI agents draw hand-drawn Excalidraw diagrams as files on your machine. This page covers its npm package (sketchdex).

### Is the Sketchdex MCP server safe to use?

Sketchdex scores 78 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 25 September 2026. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the Sketchdex MCP server expose?

Sketchdex exposes 19 tools: list_scenes, describe_scene, read_elements, read_scene, create_scene, and 14 more. Their descriptions and schemas cost roughly 5,283 tokens of context every time the server is loaded.

### Is the Sketchdex MCP server still maintained?

Sketchdex is still listed as active in the MCP registry. We last reached this channel on 25 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the Sketchdex MCP server under?

Sketchdex declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- npm package: https://www.npmjs.com/package/sketchdex
- Socket report: https://socket.dev/npm/package/sketchdex
- Repository: https://github.com/lucasr1b/sketchdex
- Website: https://sketchdex.dev/
- Changelog RSS feed: https://verifymcp.io/servers/lucasr1b-sketchdex/sketchdex.xml
- Changelog JSON feed: https://verifymcp.io/servers/lucasr1b-sketchdex/sketchdex.json
- HTML version of this page: https://verifymcp.io/servers/lucasr1b-sketchdex/sketchdex
