Skip to main content
Glama

Visual MCP

Model Context Protocol サーバーで、LLM に構造化された視覚レイヤーを提供します。「何が存在するか」を記述すると、クリーンで正確な SVG 図が返ってきます。ASCII アートではありません。


Visual MCP とは?

LLM に「アーキテクチャを描いて」と頼むと、こうなります:

+----------+      +---------+      +------------+
|  React   |----->| NestJS  |----->| PostgreSQL |
+----------+      +---------+      +------------+
                       |
                       +-----> Redis?

罫線文字は空間情報を伝えるのに適していません。配置が崩れ、矢印が届かず、後から編集できず、モデルは文字数の計算に推論力を浪費します。

明白な修正案 — 「モデルに SVG を書かせる」 — はさらに悪化します。viewBox、パスデータ、矢印の多角形、テキストのベースライン、境界線の交差を、すべて手動で、フィードバックなしに、ユーザーが小さな変更を求めるたびにゼロから計算し直さなければなりません。

Visual MCP はモデルの仕事から幾何学計算を取り除きます。 モデルはシーングラフを操作します:

{
  "title": "Service architecture",
  "elements": [
    { "id": "frontend", "type": "node",     "label": "React" },
    { "id": "backend",  "type": "node",     "label": "NestJS" },
    { "id": "db",       "type": "database", "label": "PostgreSQL" },
    { "id": "cache",    "type": "database", "label": "Redis" },

    { "id": "c1", "type": "connection", "from": "frontend", "to": "backend" },
    { "id": "c2", "type": "connection", "from": "backend",  "to": "db" },
    { "id": "c3", "type": "connection", "from": "backend",  "to": "cache" }
  ]
}

ここにないものに注目してください:座標、サイズ、線の端点、矢印、SVG は一切ありません。サーバーがすべてを計算します — ラベルからノードサイズ、接続グラフから位置、境界線に合うエッジ、矢印マーカー、テキストの折り返し、クリップしない viewBox を。

そして、シーンは安定した ID を持つグラフであるため、会話の次のターンは再描画ではなく一行の編集になります:

「Redis をバックエンドの上に、PostgreSQL をその下に置いて」 → update_element × 2、他はすべてそのまま。

「すべてのインフラを AWS というボックスの中に入れて」 → group_elements、何も移動しません。


Related MCP server: Mermaid MCP Server

アーキテクチャ

ChatGPT
   │  tool call: render_diagram / update_element / …
   ▼
MCP server            src/mcp/         (transport, tools, error shaping)
   │
   ▼
Scene graph           src/scene/       (Zod schemas, validation, store, mutations)
   │
   ├─▶ layout         src/layout/      (sizes and positions for elements with no coordinates)
   ├─▶ semantic       src/semantic/    (node/connection/axis/… ▸ primitives)
   │
   ▼
SvgNode tree          src/renderer/    (closed, allow-listed representation of an SVG document)
   │
   ├─▶ toSvgString()  ─────────────────▶  SVG returned by the MCP tools
   └─▶ <SceneRenderer> ────────────────▶  React, for the interactive UI

これを支える5つのアイデア

1. シーングラフが成果物であり、SVG は単なる出力形式です。 モデルが送信するものはすべて検証されて Scene として保存されます。レンダリングはそのシーンの純粋関数であるため、同じ図を後で別のテーマで、または別のバックエンドで、モデルを介さずに再レンダリングできます。

2. セマンティック要素はプリミティブにコンパイルされます。 database はパス、楕円、2つのテキストブロックになります。connection はマーカー付きのパスになります。レンダラーは10個のプリミティブのみを認識します。これによりレンダラーは小さく保たれ、後で neuron、decisionTree、functionPlot を追加する場合も、スキーマの共用体、レイアウトエンジン、レンダラーに変更を加えることなく、src/semantic/ に1つの展開ファイルを追加するだけで済みます。

3. 1つのジオメトリパイプライン、2つのバックエンド。 レンダラーの実際の出力は文字列ではなく SvgNode ツリーです。serialize() はそれを MCP ツール用のマークアップに変換し、<SceneRenderer> はそれを UI 用の React 要素にマッピングします。ドリフトする2つ目の実装はなく、プロジェクト内に dangerouslySetInnerHTML もありません。

4. エラーはログファイルではなく、モデル向けに書かれています。

{
  "success": false,
  "error": {
    "code": "ELEMENT_NOT_FOUND",
    "message": "Connection 'c1' points to 'router-2' (to), which does not exist in the scene.",
    "path": "c1.to",
    "hint": "Existing elements you can connect: pc, switch, router-1, server."
  }
}

分岐するためのコード、問題を特定する文、答えを含むヒント。スタックトレースは決してありません。

5. すべての変更はアトミックです。 拒否された編集は、保存されたシーンをバイト単位で元のままにします。これがなければ、1回の不正な呼び出しで、会話の残りの間、図が破損してしまいます。

当初スケッチされたレイアウトからの逸脱

  • src/layout/ は独自のモジュールであり、src/semantic/ から分離されています。配置と意味から形状への展開は異なる問題であり、この分割により、後で Dagre や ELK を導入する場合も、1つのファイル(src/layout/flow.ts)の変更で済みます。その FlowItem in / centres out インターフェースは、これらのライブラリが公開する形状を意図的に模倣しています。

  • SvgNode はレンダラーとその出力の間に位置します(上記のアイデア3)。これにより、React ビューが2つ目のレンダラーや安全でない HTML インジェクションなしで存在できるようになります。

  • src/mcp/widget.ts は依存関係のないバニラビューアであり、src/ui/ の React アプリとは別のものです。ChatGPT の iframe リソースは、ビルドステップがなく、実行時に古くなったり欠落したりする可能性のない、単一の自己完結型 HTML 文字列でなければなりません。React アプリはローカルプレイグラウンドです。両者は同じ動作(ズーム/パン/フィット/コピー/エクスポート)と同一の許可リストを共有します。

  • 自動フィットはデフォルトでオンになっているため、width/height はハードなキャンバスではなくヒントとして機能します。これにより、最も一般的な障害モード — モデルが小さすぎるキャンバスを選び、自身の図をクリップしてしまう — が排除されます。


インストール

git clone <this repo>
cd visual-mcp
npm install

Node 20 以上が必要です(Node 22/26 で開発)。


開発

npm run dev:http      # MCP server over Streamable HTTP on http://localhost:3333/mcp
npm run dev:stdio     # MCP server over stdio (Claude Desktop, MCP Inspector, tunnels)
npm run dev:ui        # React playground on http://localhost:5180
npm test              # 128 tests
npm run typecheck
npm run build         # server → dist/
npm run build:ui      # playground → dist-ui/
npm run examples      # render the reference scenes → examples/out/index.html

実行中のサーバーに対するクイックエンドツーエンドテスト:

npm run dev:http &
npx tsx scripts/smoke-mcp.ts

これはターゲットとなる会話全体を再生します — 座標なしで図を構築し、検査し、2つのノードを移動し、すべてをボックスで囲み — 各ステップで結果をアサートします。


利用可能な MCP ツール

ツール

機能

モデルが使用すべきタイミング

render_diagram

シーン全体を1回の呼び出しで構築およびレンダリングし、sceneId を返す。

描画、可視化、図示、説明、視覚的な説明を求めるあらゆるリクエスト。デフォルトのエントリポイント。

render_scene

保存されたシーンを再レンダリングする。

一連の編集後、結果を表示するため。

get_scene

シーンと、すべての要素の計算されたボックスを返す。

編集前 — 特に相対的な変更(「もう少し右に」)の場合。

add_element

1つの要素を追加する。オプションでグループ内に。

「ロードバランサーを追加」「AからBへの矢印を描いて」。

update_element

指定されたフィールドのみを変更する。null でクリア。

「それを変更して」というリクエストすべて。このために再描画はしない。

remove_element

要素を削除し、その接続とラベルをカスケード削除する。

「キャッシュを削除」。

group_elements

トップレベルの要素をラベル付きボックスで囲み、移動はしない。

「これをすべて AWS の中に入れて」「これらを VPC にグループ化」。

create_scene

空のキャンバスを作成する。

大規模な図を段階的に組み立てる場合のみ。

clear_scene

シーンを空にし、キャンバス/テーマ/タイトルは保持する。

「それはやめて、最初からやり直し」。

list_examples

動作するサンプルシーンと型カタログを返す。

何かを表現する方法がわからない場合 — コピーして適応する。

すべてのツールの説明には、機能、使用タイミング、使用すべきでないタイミング、各プロパティの意味が記載されています。これは別のモデルがこれらを読み、自ら判断するためです。読み取り専用ツールは readOnlyHint: true を、破壊的なツールは destructiveHint: true を持ち、ホストはこれらを使用して確認が必要かどうかを判断します。


シーンスキーマ

interface Scene {
  id?: string;
  title?: string;
  subtitle?: string;
  width?: number;          // hint; autoFit grows the canvas so nothing is clipped
  height?: number;
  autoFit?: boolean;       // default true
  background?: string;
  theme?: "dark" | "light" | "blueprint" | "paper";
  themeOverrides?: Partial<Theme>;
  layout?: "auto" | "layered" | "horizontal" | "vertical" | "grid" | "manual";
  direction?: "right" | "down" | "left" | "up";
  gap?: number;
  padding?: number;
  legend?: boolean;
  elements: VisualElement[];
}

すべての要素は id と type を持ちます。ID は安定しており、会話型編集の基盤です。

プリミティブ — レンダラーが描画できるもの

circle · ellipse · rectangle · line · arrow · text · polygon · polyline · path · group

セマンティック要素 — モデルが実際に使用すべきもの

型

目的

node

ラベル付きボックス。10種類の形状(rounded、circle、diamond、hexagon、cylinder、cloud、stack、screen、pill、rect)。ラベルからサイズを自動調整。接続から位置を自動配置。

connection

ID によるリンク:{ from: "a", to: "b" }。両方の境界線を見つけ、矢印を追加し、どちらかの端が移動しても正しい位置を保つ。ルーティング:straight、curved、orthogonal。

group

独自のレイアウトを持つラベル付きコンテナ。「AWS」「VLAN 10」などの境界。

axis

座標系かつデータフレーム。

point / scatter / cluster / plotLine

frame: "<axis id>" が指定された場合のデータ座標上のマーカーと線。cluster は決定論的でシード付きの点のブロブを生成する。

label

ID によって別の要素にアタッチでき、それに追従するキャプション。

server database router switch computer cloud

ドメインプリセット — 適切な形状とグリフが既に選択された node。

レイアウト

layout: "auto"(デフォルト)は、接続がある場合は接続グラフから階層的なフローを構築し、ない場合は行を構築します。明示的に x/y を持つ要素は決して移動されないため、モデルは他の要素を乱すことなく1つのノードを微調整できます。direction はフローの方向を制御します。

データフレーム

axis はデータ単位からピクセルへのマッピングを宣言します。frame: "<axis id>" を持つものはすべてデータ座標に配置され、y は期待通り上向きに増加します:

{ "id": "plot",  "type": "axis",    "x": 90, "y": 70, "width": 620, "height": 420,
  "xRange": [0, 10], "yRange": [0, 10], "xLabel": "Feature 1", "yLabel": "Feature 2" },
{ "id": "class-a", "type": "cluster", "frame": "plot", "x": 3.4, "y": 6.6,
  "count": 40, "spread": 0.8, "label": "Class A", "hull": true, "seed": 7 }

テーマ

4つの組み込みテーマ(dark、light、blueprint、paper)。それぞれが完全なパレットと、外部フォントを必要としないフォントスタックを持ちます。要素はハードコードされた色ではなくトークン(primary、surface、muted、danger)を参照するため、図全体のジオメトリに触れることなくスタイルを変更できます。themeOverrides は任意のトークンを変更できます。


ローカルでの実行

ライブラリとして(MCP なし)

import { renderScene } from "visual-mcp";

const svg = renderScene({
  title: "Request flow",
  elements: [
    { id: "client", type: "computer", label: "Client" },
    { id: "api", type: "server", label: "API" },
    { id: "c", type: "connection", from: "client", to: "api", label: "HTTPS" },
  ],
});

HTTP サーバーとして

npm run dev:http

ルート

POST /mcp

MCP Streamable HTTP エンドポイント

GET /health

ヘルスチェック

GET /scenes

保存されたシーン

GET /scenes/:id.svg

レンダリングされたシーン

GET /viewer?svg=/scenes/:id.svg

インタラクティブビューア(スタンドアロン)

サーバーはステートレスです。各リクエストは独自の McpServer とトランスポートを取得し、シーンストアのみが共有状態です。これにより、ロードバランサーの背後やサーバーレスプラットフォーム上でも安全に動作します。そこでは、1つの会話の2つのターンが同じプロセスに到達しない可能性があります。

stdio サーバーとして(MCP Inspector、Claude Desktop、Cursor)

npx @modelcontextprotocol/inspector npx tsx src/mcp/stdio.ts
{
  "mcpServers": {
    "visual-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/visual-mcp/dist/mcp/stdio.js"]
    }
  }
}

ChatGPT への接続

ChatGPT はリモート MCP サーバーに Streamable HTTP 経由でパブリックな HTTPS エンドポイント を通じて接続するため、サーバーはインターネットから到達可能である必要があります。2つの方法:

A. トンネルを使用したクイックテスト

npm run dev:http                  # http://localhost:3333/mcp
npx localtunnel --port 3333       # or: ngrok http 3333, or cloudflared tunnel

B. VPS に Docker でデプロイ

docker-compose.yml は、内部ポート4000で動作するMCPサーバー(インターネットには公開されません)と、その前でTLSを終端し、証明書を自動更新するCaddyの2つのコンテナを起動します。

このVPSには既に他のサービスがポート80と443で動作しているため、次の構成になります:

ポート

理由

HTTPS / MCPエンドポイント

500

443は既に使用中

ACME HTTP-01チャレンジ

90

80は既に使用中

MCPサーバー

4000

内部のみ、公開しない

注意点: Let's EncryptはHTTP-01のために常にポート80に接続します(これはRFC 8555で固定されており、設定変更はできません)。TLS-ALPNも同様に443に固定されています。Caddyはポート90で待ち受けることはできますが、リクエストをそこに届ける何かが必要です。そのため、ポート80を既に使用している何らかのサーバーが、チャレンジ用のパスをCaddyに転送する必要があります。

1. 公開ホスト名を選ぶ。 ChatGPTはHTTPSを必要とし、ベアIPでは証明書を取得できません。独自のドメインがない場合は、sslip.ioを使用してください。これは<ip>.sslip.ioを登録不要でそのIPに解決し、Let's Encryptがそのドメインに対して証明書を発行します:

curl -4 ifconfig.me            # on the VPS -> e.g. 203.0.113.45
# hostname becomes: 203.0.113.45.sslip.io

2. ポート80サーバーからACMEチャレンジを転送する。 まず、そのサーバーを特定します:

sudo ss -lptn 'sport = :80'

nginx — server { listen 80; } ブロック内:

location /.well-known/acme-challenge/ {
    proxy_pass http://127.0.0.1:90;
    proxy_set_header Host $host;
}

Apache — <VirtualHost *:80> 内:

ProxyPreserveHost On
ProxyPass        /.well-known/acme-challenge/ http://127.0.0.1:90/.well-known/acme-challenge/
ProxyPassReverse /.well-known/acme-challenge/ http://127.0.0.1:90/.well-known/acme-challenge/

Caddy — ポート80を提供するサイトブロック内:

handle /.well-known/acme-challenge/* {
    reverse_proxy 127.0.0.1:90
}

301リダイレクトではなく、実際のプロキシを使用してください。Let's Encryptはリダイレクトをポート80と443にのみ追従するため、 :90へのリダイレクトは失敗します。

3. 設定して起動する:

cp .env.example .env
# MCP_DOMAIN=203.0.113.45.sslip.io
docker compose up -d --build

ポート80のサーバーがホスト上ではなく、それ自身のコンテナ内で実行されている場合、127.0.0.1:90 には到達できません。.env で MCP_HTTP_BIND=0.0.0.0 を設定し、プロキシをVPSの内部IP(または両方のコンテナを同じDockerネットワーク上に配置)に向けます。

4. 確認する(最初のリクエストは、証明書が発行される間に数秒かかることがあります):

curl https://$MCP_DOMAIN:500/health       # {"status":"ok",...}
docker compose logs caddy | grep -i "certificate obtained"

MCP URLは https://<MCP_DOMAIN>:500/mcp となり、永続的です:restart: unless-stopped により再起動後も保持され、証明書は caddy_data ボリュームに保存されるため、docker compose down/up を実行しても更新は維持されます。docker compose down -v でのみ削除されます。チャレンジの転送設定は維持してください。約60日ごとの更新には、初回発行時と同様に転送が必要です。

PUBLIC_URL と ALLOWED_HOSTS は、Composeによって MCP_DOMAIN と MCP_HTTPS_PORT から派生します。両方にポートを含める必要があります:PUBLIC_URL は、そうしないと svgUrl リンクがポート443を指してしまうため、ALLOWED_HOSTS は、SDKが未加工の Host ヘッダー(標準以外のポートでは <domain>:500 となります)を正確な文字列として比較するためです。

ポート80のサーバーを操作できない場合、HTTP-01は全く利用できません。選択肢としては、DNS-01チャレンジ(対応するDNSプロバイダー上に実際のドメインが必要です — sslip.ioにはAPIがありません)、またはCloudflare Tunnelがあり、これはインバウンドポートを一切必要としません。

Composeを使用しない場合

docker build -t visual-mcp .
docker run -d --name visual-mcp --restart unless-stopped -p 127.0.0.1:4000:4000 \
  -e PUBLIC_URL=https://your-host -e ALLOWED_HOSTS=your-host visual-mcp

その後、任意のリバースプロキシを http://127.0.0.1:4000 に向けます。コンテナは非rootの node ユーザーとして実行され、/health HEALTHCHECKを出荷し、本番依存関係のみを含みます。管理対象プラットフォーム(Fly.io、Railway、Render、Cloud Run)でも動作します。これらは独自の PORT を注入し、サーバーはそれを尊重します。

その後、ChatGPTで

  1. 開発者モードを有効にする。 ChatGPT Business、Enterprise、Edu(Web版)で利用可能です。管理者がワークスペース設定 → 権限とロール → 接続データ → 開発者モード / カスタムMCPコネクタの作成で有効にします。

  2. 設定 → コネクタ → 作成 / 詳細設定 → 開発者モード → カスタムコネクタを追加。

  3. 以下の項目を入力します:

    • 名前: Visual MCP

    • MCPサーバーURL: https://<your-host>/mcp

    • 認証: 認証なし(このサーバーは認証なしで出荷されます — セキュリティを参照)

  4. 保存します。ChatGPTは直ちに tools/list を呼び出します。10個のツールがリスト表示されるはずです。

  5. 新しいチャットで、コネクタを有効にして図を依頼します。

サーバーはまた、MCP Apps UIリソース(ui://visual-mcp/scene.html、text/html;profile=mcp-app)を登録し、レンダリングツールに _meta.ui.resourceUri とChatGPTエイリアス _meta["openai/outputTemplate"] を通じて添付します。これがサポートされている場合、図はズーム、パン、フィット、コピー、エクスポート機能を備えたインタラクティブフレームに表示されます。サポートされていない場合でも、ツールは structuredContent 内にSVGを返すため、サーバーは優雅に機能を低下させます。


例

npm run examples は5つすべてを examples/out/index.html にレンダリングし、list_examples はそれらをモデルに提供します。

1. ネットワーク — examples/out/network.svg

ドメインプリセットと自動の左から右へのレイアウト。computer → switch → router → server、リンク上にVLANキャプション。ソースシーンに座標は一切ありません。

2. LDA — examples/out/lda.svg

axis データフレーム、2つのシードされたソフトハルを持つcluster、破線の決定境界、LDA方向 — すべてデータ座標で、両方の線はプロットにクリップされます。

3. 回帰 — examples/out/regression.svg

軸、scatter 系列、extend: true を指定したフィッティングされた plotLine。ライトテーマ。

4. ソフトウェアアーキテクチャ — examples/out/architecture.svg

React → REST API → { Redis, PostgreSQL }。2つのストアは、「Data layer」というラベルの付いた group 内にあり、接続はその中にルーティングされます。

5. 二分木 — examples/out/tree.svg

7つの円形ノードと6つの接続。down に流れる階層レイアウトが木を生成します。

ChatGPTで試すプロンプト

Draw the architecture where React talks to NestJS, NestJS uses PostgreSQL and also queries Redis.
Now put Redis above the backend and the database below it.
Now put all the infrastructure inside a box called AWS.
Make PostgreSQL bigger and give it a purple border.

Explain Linear Discriminant Analysis visually.
Show me graphically how linear regression works.
Draw a network where a PC in VLAN 20 reaches a server in VLAN 10 through a switch and a router.
Draw a balanced binary tree with 7 nodes.
Explain the TCP three-way handshake as a diagram.
Diagram merge sort on [5, 2, 9, 1].

セキュリティ

脅威モデルはシンプルです:サーバーがレンダリングするものはすべて言語モデルから発信され、その出力自体にユーザーが他の場所から貼り付けたテキストが含まれている可能性があります。そのため、モデル由来のものは決してコードとして扱われません。

  • 閉じられたスキーマ。 既知の24の要素タイプのみが解析されます。色は hex/rgb/hsl/keyword/token の文法と一致する必要があります — url(javascript:…) は検証時に拒否されます。パスデータはSVGパスコマンドと数値のみと一致する必要があり、それ以外は許可されません。

  • 許可リスト化された出力。 レンダラーは src/renderer/svgNode.ts 内の2つの明示的なリストからのタグと属性のみを出力できます。on*、href、style、class、<foreignObject>、<script> は存在しません — モデルはそれらを表現できず、シリアライザーはそれらを破棄します。

  • エスケープ。 テキストコンテンツと属性値は、出力時にXMLエスケープされます。

  • プロジェクト全体に dangerouslySetInnerHTML、eval、new Function は一切ありません。 Reactビューは SvgNode ツリーから要素を構築します。ChatGPTウィジェットはSVGを解析し、同じ許可リストに対してノードごとに再構築します。そのため、サーバーが侵害されたとしても、スクリプトがそのフレームに入り込むことはできません。

  • 入力に制限あり。 要素数、文字列長、ポイント数、パス長、保存されたシーンはすべて上限があり、シーンは最も古いものから削除されます。

  • モデルへのスタックトレースはなし。 すべてのハンドラーはラップされており、予期しないものはすべて短いメッセージと共に INTERNAL_ERROR になります。

tests/security.test.tsx のテストは、これらの各項目をアサートします。

設計上、含まれていません: 認証。このサーバーはシークレットを公開せず、外部システムに触れませんが、パブリックなデプロイメントは公開されたシーンストアです。自分自身以外に公開する前に、プラットフォームの認証の背後に配置するか、SDKの認証ヘルパーを介してOAuthを追加してください。ALLOWED_HOSTS を設定して、ブラウザから到達可能な場合にDNSリバインディング保護を有効にします。


現在の制限事項

  • テキストメトリクスは推定値であり、測定値ではありません — サーバーにフォントエンジンはありません。バンドルされたサンセリフスタックの幅は数パーセントの誤差範囲内であり、ボックスと折り返しには十分ですが、珍しいフォントや多くのCJK文字ではサイズが多少ずれる可能性があります。

  • レイアウトエンジンは意図的に小規模です。 最長パスレイヤリングとランクセンタリングを使用します。交差最小化やオーバーラップ解決はないため、密なグラフ(おおよそ25ノード以上で多くのクロスリンクがある場合)では、本格的なエンジンが回避する交差が発生します。インターフェースはまさにこの理由でDagreの形状をしています。

  • ツリーレイアウトは子中心ではありません。 親はその子の中間点の上ではなく、そのランクの中心に配置されます。

  • render_diagram のJSON Schemaは約50 KB(約12kトークン)です。 これは要素の語彙全体を教えるためです。他の9つのツールは合計で約5 KBです。これは意図的なトレードオフです。モデルはフィールドごとのドキュメントを取得し、修正のためのラウンドトリップがほとんど必要なくなります。

  • 自動レイアウトのグループ内では、子の明示的な x/y は無視されます — レイアウトが優先されます。子を自分で配置するには、グループに layout: "manual" を使用します。

  • ストレージはインメモリです。 シーンは再起動後も保持されず、複数のレプリカがある場合、シーンは它を作成したインスタンス上にのみ存在します。SceneStore インターフェースは、このクラスを置き換えるために存在します。

  • 静的出力。 アニメーション、3D、数式パーサーはまだありません — 以下を参照してください。


ロードマップ

次

  • 永続的な SceneStore(まずはSQLite) — インターフェースは既に整っています。

  • 元に戻す/やり直す。すべての変更は既に SceneMutation として記録されています。これは逆の操作を保存する問題です。

  • 密なグラフのための、src/layout/flow.ts の背後にあるDagreまたはELK。小規模エンジンをデフォルトとします。

  • 子中心のツリーレイアウト。

数式 — axis データフレームが基礎です。これらはそれぞれ src/semantic/ 内の1つのエクスパンダーであり、レンダラーの変更はありません: functionPlot({ "expression": "x^2", "domain": [-5, 5] })、vector、matrix、plane、distribution、projection、decisionBoundary、regressionLine(plotLine の名前付きエイリアスとして)。

図の語彙 — neuron、neuralNetwork、decisionTree、sequenceDiagram、stateMachine、gantt、swimlane。

アニメーション — 接続上の { "animation": { "type": "flow", "duration": 1200 } }。SVG SMILまたはCSSとして出力されるため、宣言的であり、ランタイムを必要としません。リンクに沿って移動するパケット、パイプラインを通過するリクエスト、構造をステップ実行するアルゴリズムなど。

その他のレンダラー — 解決パイプラインは、すでにバックエンドに依存しないツリーで終了します。kind: "3d" と { "type": "sphere", "position": [0, 1, 0] } を持つ Scene は、SVGバックエンドの代わりにThree.jsバックエンドを選択します。Canvasバックエンドは非常に大きな散布図を提供します。MCPレイヤーへの変更はありません。


ライセンス

MIT

Available Tools

10 tools
add_elementAdd an elementA

Add one element to a scene that already exists.

USE THIS when the user wants something new in a diagram you already drew: "add a load balancer", "put a Redis cache next to the API", "draw an arrow from A to B".

Call get_scene first if you are not certain which ids exist. To link the new element to an existing one, make a second call with an element of type 'connection' referencing the two ids - the geometry is computed for you.

Omit x/y and the layout engine places it. Set parentId to put it inside a group.

This does not display anything. Call render_scene once your edits are done.

ParametersJSON Schema
NameRequiredDescriptionDefault
elementYesThe element to add: an object with a unique `id`, a `type`, and the properties of that type - exactly the same shape as the entries of `elements` in render_diagram. Types: node, connection, group, axis, point, scatter, cluster, plotLine, label, server, database, router, switch, computer, cloud, circle, ellipse, rectangle, line, arrow, text, polygon, polyline, path. Example: { "id": "cache", "type": "database", "label": "Redis" }.
sceneIdYesId of the scene to work on, as returned by render_diagram or create_scene.
parentIdNoId of a 'group' element to nest this inside.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent only when success is false.
sceneIdNo
successYes
elementIdNo
elementCountNoTop-level elements in the scene after the add.

TDQS

A4.9/5.0
Behavior5/5

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

Beyond the annotations (which are all false and give no safety hints), the description richly discloses behavior: 'Omit x/y and the layout engine places it', 'the geometry is computed for you', and 'This does not display anything. Call render_scene once your edits are done.' It also explains that parentId nests the element inside a group. These are meaningful behavioral traits not present in annotations or schema descriptions.

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?

The description is well-structured and front-loaded: a one-sentence summary, a bold 'USE THIS' callout, then prerequisites, special cases, and rendering note. Every sentence adds unique value—no fluff or repetition of schema content. It is compact despite covering multiple scenarios (first-time adds, connections, layout, grouping, rendering).

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

Completeness5/5

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

The description is remarkably complete for a tool with nested objects and 3 parameters. It covers prerequisites (get_scene), the exact workflow for linking elements (connection type), layout behavior (omit x/y), grouping (parentId), and the follow-up step (render_scene). Since an output schema exists, the lack of return-value explanation is acceptable. The tool feels self-contained for an agent to invoke successfully.

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 description coverage is 100%, so parameters are well-documented in the schema. The tool description nevertheless adds significant value: it explains that the element object is 'exactly the same shape as the entries of elements in render_diagram', provides a concrete example, and clarifies behavior of x/y (omit for auto-layout). This goes beyond the schema, though the core parameter meanings are already covered, so a 4 is appropriate rather than 5.

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?

The description opens with a clear, specific statement: 'Add one element to a scene that already exists.' This uses a strong verb ('Add'), defines the resource ('element'), and the target ('scene'). It distinguishes itself from sibling tools like update_element, remove_element, and group_elements by focusing solely on adding new elements. Concrete usage examples ('add a load balancer', 'draw an arrow from A to B') further clarify the purpose.

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

Usage Guidelines5/5

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

Explicit 'USE THIS' guidance tells the agent exactly when to apply the tool: 'when the user wants something new in a diagram you already drew.' It also provides alternative and prerequisite actions: 'Call get_scene first if you are not certain which ids exist' and 'Call render_scene once your edits are done.' The connection workflow is explained with 'make a second call with an element of type 'connection'', giving clear usage boundaries.

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

clear_sceneEmpty a sceneA
DestructiveIdempotent

Remove every element from a scene while keeping its id, canvas, theme and title.

USE THIS when the user wants to restart the drawing but keep talking about the same diagram: "scrap that, let's do it differently".

DO NOT use it for corrections - update_element and remove_element exist for that, and they preserve everything the user already approved.

ParametersJSON Schema
NameRequiredDescriptionDefault
sceneIdYesId of the scene to work on, as returned by render_diagram or create_scene.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent only when success is false.
sceneIdNo
successYes

TDQS

A4.7/5.0
Behavior4/5

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

The description adds significant behavioral context beyond what annotations provide. Annotations already indicate destructiveHint=true, so the destructive nature is known. But the description clarifies exactly what is destroyed (every element) and what is preserved (id, canvas, theme, title). It also notes that this is idempotent (idempotentHint=true is already in annotations). The only missing detail is whether undo is possible or what the output schema returns, but the output schema exists to specify that.

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?

The description is three sentences with zero wasted words. The first sentence defines purpose and scope concisely. The second and third sentences provide usage guidelines and sibling differentiation in a clear, front-loaded manner. The 'USE THIS when' and 'DO NOT use it' structure is exceptionally clear.

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

Completeness5/5

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

Given the simple tool with only one parameter, clear annotations, and an output schema, the description is complete. It covers purpose, scope, preservation details, usage context, and exclusions. There is no missing critical information for an AI agent to correctly select and invoke this 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?

Schema description coverage is 100% for the single parameter, and the schema already documents that sceneId must match a specific pattern and length, and gives a helpful description. The description adds context by referring to 'as returned by render_diagram or create_scene', which helps in understanding how to obtain the correct ID. This surpasses the baseline of 3.

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?

The description clearly states the tool removes every element from a scene while preserving its id, canvas, theme, and title. It specifies the verb 'Remove every element' and the resource 'scene', and distinguishes itself from siblings like update_element and remove_element by describing its unique behavior of clearing all elements.

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

Usage Guidelines5/5

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

The description explicitly tells when to use the tool ('when the user wants to restart the drawing but keep talking about the same diagram') and provides a concrete user utterance ('scrap that, let's do it differently'). It also explicitly tells when NOT to use it ('DO NOT use it for corrections') and names the appropriate alternatives (update_element and remove_element).

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

create_sceneCreate an empty sceneA

Create a new, empty scene and get back its id.

USE THIS when you want to build a diagram incrementally - create the canvas, then add elements one at a time with add_element, then call render_scene when it is complete.

DO NOT use this when you already know the whole picture: render_diagram does the same job in one round trip and is almost always the better choice. Incremental building is only worth it for large diagrams you are assembling as the conversation goes.

Nothing is shown to the user until you call render_scene.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoStable, meaningful id (e.g. 'backend'). Reuse it later to update or remove this element.
gapNoSpacing used by the automatic layout. Default 90.
themeNoVisual theme. 'dark' (default) is a modern technical look, 'light' is for documents, 'blueprint' is a blue schematic, 'paper' is warm and printable.
titleNoDiagram title, drawn at the top. Keep it short - it is a caption, not a sentence.
widthNoCanvas width in pixels. Default 960. Use 1200+ for wide flows.
heightNoCanvas height in pixels. Default 600.
layoutNoHow elements without explicit x/y are placed. 'auto' (default) builds a layered flow from the connections when there are any, otherwise a row. 'layered' forces the flow layout, 'horizontal'/'vertical'/'grid' force a simple arrangement, 'manual' means you provide every x/y yourself.
legendNoShow a legend built from the `label` of scatter/cluster series. Default true.
autoFitNoGrow the canvas so nothing is clipped. Default true - leave it on and stop worrying about exact sizes.
paddingNoMargin around the drawing. Default 48.
subtitleNoOptional second line under the title.
directionNoDirection the layered flow grows in. Default 'right'.
backgroundNoCanvas background. Defaults to the theme background.
themeOverridesNoOptional palette overrides. Only set what you actually want to change.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageYes
sceneIdYes
successYes

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false and destructiveHint=false. The description adds that the scene is empty and that user sees nothing until render_scene is called. This context about the multi-step workflow goes beyond the annotations without contradicting them.

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?

The description is extremely concise: three short paragraphs. The first sentence states purpose, the second gives usage direction, the third provides an important behavioral note. Every sentence earns its place with zero padding.

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?

Given the tool has 14 parameters (fully documented in the schema) and an output schema, the description does not need to cover those. It provides the essential workflow context—that this is part of a multi-step process culminating in render_scene—and explains the trade-off with render_diagram, which is sufficient for an agent to decide when to invoke.

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 100%—every parameter has a detailed description in the schema. The tool description does not add new parameter-level information but also does not repeat what the schema provides, so baseline 3 is appropriate.

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?

The description opens with 'Create a new, empty scene and get back its id,' which is a specific verb+resource statement. It clearly distinguishes from siblings like 'render_diagram' (alternative for known pictures) and 'add_element' (incremental step).

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

Usage Guidelines5/5

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

Explicit 'USE THIS' section describes when to use (incremental building) and 'DO NOT use this' section points to the sibling 'render_diagram' as the better choice for one-shot creation. Also clarifies that nothing is shown until 'render_scene' is called.

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

get_sceneInspect a sceneA
Read-onlyIdempotent

Return the current structured description of a scene: every element with its id, type and properties, plus the position and size each one actually ended up with.

USE THIS BEFORE EDITING whenever you are not sure of the current state - which ids exist, what a node is called, where it sits, what is already connected. Reading first is what makes small edits possible instead of redrawing the diagram from scratch.

The layout field gives the computed box (x, y, width, height) of every element, including ones you never gave coordinates to. Those are the numbers to use when the user asks for something relative: "a bit to the right", "above the backend", "same width as X".

This does not display anything.

ParametersJSON Schema
NameRequiredDescriptionDefault
sceneIdYesId of the scene to work on, as returned by render_diagram or create_scene.
elementIdNoReturn just this one element instead of the whole scene.
includeLayoutNoInclude the computed box of every element. Default true.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idsNoEvery element id in the scene.
errorNoPresent only when success is false.
sceneNoThe full scene, ready to be edited or re-sent.
layoutNoMap of element id to { x, y, width, height }.
elementNo
historyNoThe last few mutations applied to this scene.
sceneIdNo
successYes

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false. The description adds valuable behavioral context: the layout field includes computed boxes for elements never given coordinates, and it warns that the tool does not display anything. This goes beyond the safety profile provided by annotations.

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?

The description is compact and front-loaded: it states the main function in the first sentence, then provides targeted usage guidance and a caveat. Every sentence earns its place, and the bolded 'USE THIS BEFORE EDITING' plus the final 'This does not display anything' are high-signal phrases with no filler.

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

Completeness5/5

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

With full annotations, a complete input schema (100% coverage), and an output schema, the description supplies all necessary operational context: when to use, what to expect, and a key caveat about non-display. No critical gaps remain for a read-only inspection 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?

Schema description coverage is 100%, with clear descriptions for all three parameters, giving a baseline of 3. The description adds extra meaning by explaining the layout field operationally—'the computed box (x, y, width, height) of every element, including ones you never gave coordinates to'—which clarifies how to use parameters for relative positioning.

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?

The description uses a specific verb and resource: 'Return the current structured description of a scene' and enumerates the exact contents (id, type, properties, position, size). It also clearly distinguishes itself from rendering siblings with the explicit note 'This does not display anything.'

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?

The description explicitly states when to use it: 'USE THIS BEFORE EDITING whenever you are not sure of the current state.' It also implies exclusions (not for display) but does not explicitly name alternative tools like render_diagram, so it stops short of a full 5.

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

group_elementsGroup elements into a labelled boxA

Wrap existing top-level elements in a labelled container.

USE THIS for "put all of this inside a box called AWS", "group these services into a VPC", "draw a boundary around the data layer", "show which parts are in VLAN 10".

The members keep their ids, and every connection to or from them keeps working - including connections that cross the boundary.

Set layout to re-arrange the members inside the box ('vertical' stacks them, 'horizontal' puts them in a row, 'grid' wraps them). Leave it out to keep their current arrangement.

Only top-level elements can be grouped. To nest a group inside another group, create the inner one first, then group it together with its siblings.

ParametersJSON Schema
NameRequiredDescriptionDefault
fillNoBackground colour.
labelNoText drawn on the box, e.g. 'AWS'.
layoutNoRe-arrange the members. Default 'manual' (keep their current positions).
strokeNoBorder colour.
groupIdYesId for the new group, e.g. 'aws' or 'vlan-10'.
sceneIdYesId of the scene to work on, as returned by render_diagram or create_scene.
elementIdsYesIds of the top-level elements to move inside the box.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent only when success is false.
groupIdNo
membersNo
sceneIdNo
successYes

TDQS

A4.9/5.0
Behavior5/5

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

The description goes well beyond the annotations (which only mark non-read-only/non-destructive) by detailing behavioral traits: 'The members keep their ids, and every connection to or from them keeps working - including connections that cross the boundary.' It also explains how the layout parameter affects arrangement and the default behavior ('manual' keeps current positions). This provides rich behavioral context the agent needs for safe invocation.

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?

The description is concise yet comprehensive, with only 9 sentences. It front-loads the core purpose, then provides usage examples, behavioral guarantees, parameter guidance, and a crucial limitation for nesting. Every sentence adds unique value without redundancy.

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

Completeness5/5

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

Given the tool's complexity (7 parameters, 3 required, 100% schema coverage, output schema present), the description is complete. It explains the grouping behavior, parameter effects, constraints ('Only top-level elements can be grouped'), and nesting strategy. There are no gaps in understanding what the tool does or how to use it correctly.

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?

With 100% schema description coverage, the schema already documents all parameters thoroughly. The description adds value by explaining the layout parameter options in natural language ('vertical stacks them, horizontal puts them in a row, grid wraps them') and clarifying the scope of elementIds ('top-level elements'). However, it doesn't add meaning to all 7 parameters (e.g., fill, stroke, sceneId are not elaborated beyond schema).

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?

The description opens with a specific verb+resource ('Wrap existing top-level elements in a labelled container'), immediately clarifying what the tool does. It is easily distinguishable from siblings like 'add_element' (which adds individual elements, not grouping) and 'render_diagram' (which visualizes the whole scene). The examples concretely illustrate its scope and differentiate it from other tools.

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

Usage Guidelines5/5

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

The description provides explicit usage examples ('put all of this inside a box called AWS'), including when to use it ('group these services into a VPC') and a clear limitation ('Only top-level elements can be grouped') with guidance on how to handle nesting ('create the inner one first, then group it together with its siblings'). This effectively tells the agent when and how to use this tool over alternatives.

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

list_examplesShow example scenesA
Read-onlyIdempotent

Return complete, working example scenes for common kinds of diagram.

USE THIS when you are unsure how to express something with this server: which element type fits, how data frames work, how to nest a group. Copy the closest example and adapt it - that is faster and more reliable than guessing at the schema.

Call it with no arguments for the catalogue, or with name for one full scene you can pass straight to render_diagram.

Available: network, lda, regression, architecture, tree.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoReturn the full scene for this example. Omit for the catalogue.

Output Schema

ParametersJSON Schema
NameRequiredDescription
sceneNo
successYes
examplesNo
elementTypesNo

TDQS

A4.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is clear. The description adds the behavioral insight that calling with 'name' returns a full renderable scene, which goes beyond the schema. However, it does not detail what the output looks like or that it should be passed to render_diagram, though the token 'render_diagram' hints at integration. With annotations covering safety, a score of 3 is appropriate.

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?

The description is concise with no wasted words. It front-loads the core purpose, immediately follows with usage guidance, and ends with a clear list of available examples. Every sentence contributes meaning.

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?

Given the tool's low complexity (1 parameter, no required ones, enums documented, output schema exists), the description is largely complete. It explains the tool's role, how to invoke it, and the available options. A minor gap is not explicitly stating that the output scene is meant for render_diagram, but the sibling context and the phrase 'pass straight to render_diagram' cover this adequately.

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 100%, so the schema already documents the single parameter 'name' with enum values. The description adds value by explaining the two usage modes (no args vs with name) and lists the available examples in the enum. However, it repeats what the enum provides, offering only incremental context. Baseline 3 is correct.

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?

The description clearly defines the tool's purpose with a specific verb-resource pair: 'Return complete, working example scenes.' It distinguishes the tool from siblings by stating these are examples to help when unsure about schema usage, unlike render_diagram or get_scene which serve different functions.

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

Usage Guidelines5/5

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

The description explicitly states when to use this tool ('when you are unsure how to express something'), advises against alternatives ('guessing at the schema'), and provides a behavioral tip ('Copy the closest example and adapt it - that is faster and more reliable'). It also clarifies the two calling modes: no arguments for catalogue, or with name for a full scene.

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

remove_elementRemove an elementA
DestructiveIdempotent

Delete one element from a scene.

USE THIS for "remove the cache", "delete that arrow", "drop the second database".

Connections pointing at the element, and labels attached to it, are deleted with it by default - otherwise the scene would keep dangling references. Set cascade to false only if you plan to repair those references yourself in the same turn.

Removing a 'group' also removes everything inside it. To keep the children, update the group instead and set frame to false.

ParametersJSON Schema
NameRequiredDescriptionDefault
cascadeNoAlso remove connections and labels attached to it. Default true.
sceneIdYesId of the scene to work on, as returned by render_diagram or create_scene.
elementIdYesId of the element to remove.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent only when success is false.
removedNoEvery id that was deleted, including cascaded ones.
sceneIdNo
successYes

TDQS

A4.9/5.0
Behavior5/5

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

Beyond annotations (destructiveHint=true), the description details the cascade behavior, deletion of connections and labels, and implications for groups. It warns about dangling references and when to set cascade=false, providing rich behavioral insight.

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?

The description is well-structured: opening purpose statement, usage examples, behavioral detail, and a specific note on groups. Every sentence adds value, no fluff, and it's appropriately compact for the complexity.

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

Completeness5/5

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

Given the tool's destructive nature and edge cases (dependencies, groups), the description covers all necessary aspects. It explains when to use, side effects, parameter nuances, and alternative actions. With an output schema present, no return-value explanation is needed.

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 covers all parameters at 100%, so baseline is 3. The description adds value by explaining cascade semantics in depth (when to use false) and the group removal behavior, which goes beyond the schema's simple descriptions.

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?

The description clearly states 'Delete one element from a scene' with a specific verb and resource. It distinguishes from siblings by giving usage examples like 'remove the cache' and contrasts with add_element/update_element. The purpose is unambiguous and well-scoped.

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

Usage Guidelines5/5

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

Explicitly tells the agent when to use it with 'USE THIS for...' and provides examples. It also gives guidance on when not to use cascade and advises updating the group instead to keep children. This is excellent context for selecting the tool over alternatives.

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

render_diagramRender a diagramA

Create and render a structured visual diagram as SVG, in a single call.

USE THIS whenever the user asks to draw, sketch, visualise, diagram, illustrate, map out, show graphically, explain visually, or represent something spatially: architectures, network topologies, flows, pipelines, data structures, algorithms, state machines, relationships, plots, distributions, classifiers, or any concept where position and connection carry meaning.

ALWAYS PREFER THIS OVER ASCII ART, box-drawing characters, Markdown tables used as layout, or hand-written SVG/Mermaid. Those are unreliable and hard to read; this tool produces a precise, styled picture and the user sees it directly.

HOW TO USE IT WELL:

  • Describe WHAT exists, not WHERE it goes. Give elements ids and labels and omit x/y: the layout engine positions them from the connections. Only set x/y when the user asks for a specific arrangement, or for plots built on an axis.

  • Link things with { type: 'connection', from: '<id>', to: '<id>' }. Never compute x1/y1/x2/y2 for a link between elements, and never draw arrowheads by hand.

  • Use semantic types (node, database, server, router, switch, computer, cloud, group, axis, cluster, scatter, plotLine, label) before reaching for raw primitives (circle, rectangle, line, arrow, text, path, ...).

  • Canvas size is optional: the drawing is auto-fitted so nothing is ever clipped.

DO NOT use this tool for: plain prose answers, code, tables of numbers, or when the user explicitly asked for text only.

Returns a sceneId. Keep it: later edits go through update_element / add_element / remove_element on that id instead of rebuilding the whole scene.

ParametersJSON Schema
NameRequiredDescriptionDefault
gapNoSpacing used by the automatic layout. Default 90.
themeNoVisual theme. 'dark' (default) is a modern technical look, 'light' is for documents, 'blueprint' is a blue schematic, 'paper' is warm and printable.
titleNoDiagram title, drawn at the top. Keep it short - it is a caption, not a sentence.
widthNoCanvas width in pixels. Default 960. Use 1200+ for wide flows.
heightNoCanvas height in pixels. Default 600.
layoutNoHow elements without explicit x/y are placed. 'auto' (default) builds a layered flow from the connections when there are any, otherwise a row. 'layered' forces the flow layout, 'horizontal'/'vertical'/'grid' force a simple arrangement, 'manual' means you provide every x/y yourself.
legendNoShow a legend built from the `label` of scatter/cluster series. Default true.
autoFitNoGrow the canvas so nothing is clipped. Default true - leave it on and stop worrying about exact sizes.
paddingNoMargin around the drawing. Default 48.
elementsYesEverything in the picture. Order matters: later elements are drawn on top.
subtitleNoOptional second line under the title.
directionNoDirection the layered flow grows in. Default 'right'.
backgroundNoCanvas background. Defaults to the theme background.
themeOverridesNoOptional palette overrides. Only set what you actually want to change.

Output Schema

ParametersJSON Schema
NameRequiredDescription
svgNoThe rendered SVG markup.
titleNo
widthYes
formatYes
heightYes
svgUrlNoDirect link to the rendered SVG, when deployed.
sceneIdYesUse this id with get_scene / update_element / add_element.
successYes
elementCountYes

TDQS

A4.6/5.0
Behavior4/5

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

Annotations declare readOnlyHint=false, destructiveHint=false, idempotentHint=false, openWorldHint=false. The description goes beyond these by disclosing specific behavioral traits: 'the layout engine positions them from the connections', 'Canvas size is optional: the drawing is auto-fitted', 'Order matters: later elements are drawn on top', and 'Returns a sceneId. Keep it: later edits go through update_element / add_element / remove_element on that id.' This is rich context beyond just the boolean hints.

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 front-loaded with the essential purpose in the first sentence, then branches into use cases, usage rules, best practices, and exclusions. It is quite long but every section earns its place—the 'HOW TO USE IT WELL' section is especially valuable for correct tool invocation. One minor redundancy: 'DO NOT use this tool for: plain prose answers, code, tables of numbers, or when the user explicitly asked for text only' could be slightly tighter, but overall it's well-structured and efficient for the complexity.

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

Completeness5/5

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

Given the high complexity (14 params, nested objects, 21 element types), the description is remarkably complete. It covers creation, layout guidance, element semantics, positioning philosophy, return value ('Returns a sceneId'), and lifecycle ('later edits go through update_element / add_element / remove_element'). An output schema exists, so return value details don't need to be in the description. The description fully equips an agent to invoke this tool correctly across a wide range of diagram types.

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 description coverage is 100%, so baseline is 3. The description adds significant meaning beyond the schema: it explains layout philosophy ('Describe WHAT exists, not WHERE it goes', 'omit x/y: the layout engine positions them'), provides best-practice usage for connections ('Link things with { type: 'connection', from: '<id>', to: '<id>' }'), lists semantic element types to prefer, and gives theme descriptions (''dark' (default) is a modern technical look'). This goes well above the baseline.

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?

The description explicitly states 'Create and render a structured visual diagram as SVG, in a single call.' It lists specific use cases like architectures, network topologies, flows, plots, etc., and distinguishes this tool from alternatives like ASCII art, Mermaid, or manual SVG by asserting 'ALWAYS PREFER THIS OVER...'. The verb+resource combo is very specific, and the guidance on when to use it versus parents like add_element or create_scene is clear.

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

Usage Guidelines5/5

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

The description includes a 'USE THIS whenever the user asks...' block listing numerous contexts (visualize, map out, diagram, etc.) and a 'DO NOT use this tool for' block excluding plain prose, code, or pure-text requests. It also advises 'ALWAYS PREFER THIS OVER ASCII ART, box-drawing characters...' and mentions alternatives ('later edits go through update_element / add_element / remove_element'). This provides comprehensive when-to-use and when-not-to-use guidance.

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

render_sceneRender an existing sceneA
Read-onlyIdempotent

Render a stored scene and show it to the user.

USE THIS after a batch of add_element / update_element / remove_element / group_elements calls, to display the updated diagram. It is the last step of every edit.

This never changes the scene - it only draws what is currently in it. For a brand new diagram use render_diagram instead, which builds and shows it in one call.

ParametersJSON Schema
NameRequiredDescriptionDefault
sceneIdYesId of the scene to work on, as returned by render_diagram or create_scene.

Output Schema

ParametersJSON Schema
NameRequiredDescription
svgNoThe rendered SVG markup.
errorNoPresent only when success is false.
titleNo
widthNo
formatNo
heightNo
svgUrlNoStable link to the rendered SVG, when deployed.
sceneIdNo
successYes
elementCountNo

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already provide readOnlyHint=true, idempotentHint=true, destructiveHint=false. The description adds value by explaining the tool 'never changes the scene - it only draws what is currently in it', which reinforces the behavioral contract beyond the annotations. A slight deduction is that it doesn't mention any potential rendering delays or failure modes.

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?

The description is extremely concise with only three sentences, all front-loaded with the core purpose. Every sentence adds value: purpose, usage guidelines, and exclusion of alternatives. No wasted words.

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

Completeness5/5

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

Given the tool has 1 parameter with full schema coverage, an output schema, and comprehensive annotations, the description is complete. It provides all necessary context for an agent to select and invoke this tool correctly: purpose, usage flow, behavioral safety, parameter source, and sibling differentiation.

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 100%, so the baseline is 3. The description adds some value by mentioning the sceneId is 'as returned by render_diagram or create_scene', providing context on how to obtain valid IDs. However, it doesn't add new meaning about the parameter format beyond the schema's pattern.

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?

The description clearly states this tool renders a stored scene and shows it to the user. It uses specific verbs ('render', 'show', 'display') and identifies the resource ('stored scene', 'updated diagram'), distinguishing it from siblings like render_diagram which builds a new diagram.

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

Usage Guidelines5/5

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

The description explicitly tells when to use this tool: after a batch of editing calls (add_element, update_element, etc.) as the last step of every edit. It also clearly states when NOT to use it: for brand new diagrams, use render_diagram instead. This provides excellent context for an AI agent to decide.

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

update_elementUpdate an elementA
Idempotent

Change properties of one element. Only the fields you send are touched; everything else in the scene stays exactly as it is.

USE THIS for every 'change that' request: move it, resize it, recolour it, rename its label, make a link dashed, add a caption to a connection. For a relative move like "a bit to the right", read the current position with get_scene and send the new value.

DO NOT call render_diagram again to change one thing. That throws away the scene id, the layout and everything the user already accepted.

id and type cannot be changed - remove and re-add the element if you truly need that. Send null as a value to clear an optional property; for example { "x": null, "y": null } hands the element back to the automatic layout.

Nothing is displayed until you call render_scene.

ParametersJSON Schema
NameRequiredDescriptionDefault
changesYesProperties to set. Examples: { "x": 420 } to move, { "label": "PostgreSQL 16" } to rename, { "fill": "primary", "emphasis": "strong" } to highlight, { "dash": "dashed" } on a connection, { "width": 240, "height": 120 } to resize. null clears an optional property.
sceneIdYesId of the scene to work on, as returned by render_diagram or create_scene.
elementIdYesId of the element to change.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent only when success is false.
elementNoThe element after the change.
sceneIdNo
successYes
elementIdNo

TDQS

A5/5.0
Behavior5/5

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

The annotations already mark destructiveHint=false and readOnlyHint=false, so mutation is expected. The description goes far beyond by explaining partial update semantics ('Only the fields you send are touched'), immutability of id and type, how to clear properties with null, and the critical fact that nothing is displayed until render_scene is called. No contradiction with annotations.

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?

The description is four paragraphs, each focused on a distinct aspect (what the tool does, use-cases, anti-patterns, edge cases/immutability/clearing, and rendering dependency). Every sentence serves a purpose; no wasted words.

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

Completeness5/5

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

Given the tool's complexity (3 params, all required, one being a nested object), the description fully covers usage, limitations, behavioral nuances, and integration with sibling tools. An output schema exists, so return values are not needed in the description.

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

Parameters5/5

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

Schema coverage is 100%, but the description adds enormous value: it explains how to use the `changes` parameter with concrete examples, clarifies that null clears optional properties, and eliminates ambiguity around partial updates. The schema itself is well-described, but the description contextualizes the schema's static definitions into actionable guidance.

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?

The description uses the specific verb 'Change properties' targeting 'one element', clearly distinguishing it from sibling tools like add_element or remove_element. It also explicitly calls out what it does and does not do, making its purpose unmistakable.

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

Usage Guidelines5/5

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

The description provides excellent usage guidance: it tells when to use this tool ('USE THIS for every change that request'), provides examples of specific changes, and explicitly tells when NOT to use alternatives ('DO NOT call render_diagram again to change one thing'). It also gives a relative-move workaround using get_scene.

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. 10 tool updatesv0.1.0
    • First observedadd_element
    • First observedclear_scene
    • First observedcreate_scene
    • First observedget_scene
    • First observedgroup_elements
    • First observedlist_examples
    • First observedremove_element
    • First observedrender_diagram
    • First observedrender_scene
    • First observedupdate_element

TDQS

A4.6/5.0

Scored across 10 tools

Disambiguation5/5

Each tool targets a distinct phase of the diagram lifecycle: create-and-render, render-existing, inspect, mutate, group, clear, and example lookup. The descriptions clearly separate render_diagram from create_scene/render_scene and get_scene from render_scene, so an agent should not misselect.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern: render_diagram, get_scene, add_element, update_element, remove_element, group_elements, clear_scene. The convention is uniform and predictable across the entire set.

Tool Count5/5

10 tools is well-scoped for a diagramming server: one call for whole diagrams, plus granular create/read/update/delete/render/group operations. Each tool serves a clear purpose without redundancy or bloat.

Completeness4/5

The lifecycle is well covered: create, render, inspect, add, update, remove, group, clear, and example guidance. The main gap is the lack of a dedicated ungroup operation, and there is no scene deletion/list tool, though clear_scene mitigates restart scenarios.

Maintenance

ActivityStale
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers