Visual MCP
Visual MCP
Ein Model Context Protocol Server, der einer KI eine strukturierte visuelle Ebene bereitstellt: Er beschreibt, was existiert, und erhält ein sauberes, präzises SVG-Diagramm zurück – anstelle von ASCII-Art.
Was ist Visual MCP?
Bittet man eine KI, "die Architektur zu zeichnen", erhält man dies:
+----------+ +---------+ +------------+
| React |----->| NestJS |----->| PostgreSQL |
+----------+ +---------+ +------------+
|
+-----> Redis?Box-Zeichen sind ein schlechtes Medium für räumliche Informationen. Ausrichtung bricht, Pfeile erreichen ihr Ziel nicht, nichts lässt sich nachträglich bearbeiten, und das Modell verbraucht Rechenleistung für das Zählen von Zeichen.
Die naheliegende Lösung – "die KI SVG schreiben lassen" – ist noch schlimmer. Dann muss sie viewBoxes, Pfaddaten, Pfeilspitzen-Polygone, Textbaselines und Randüberschneidungen berechnen, alles von Hand, alles ohne Rückmeldung, und alles wieder von Grund auf, sobald der Benutzer eine kleine Änderung wünscht.
Visual MCP entfernt die Geometrie aus der Aufgabe des Modells. Das Modell arbeitet mit einem Szenengraphen:
{
"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" }
]
}Beachten Sie, was nicht da ist: keine Koordinaten, keine Größen, keine Linienendpunkte, keine Pfeilspitzen, kein SVG. Der Server berechnet alles – Knotengrößen aus den Beschriftungen, Positionen aus dem Verbindungsgraphen, Kanten, die die Ränder treffen, Pfeilspitzenmarkierungen, Textumbruch und eine viewBox, die nichts abschneiden kann.
Und weil die Szene ein Graph mit stabilen IDs ist, ist der nächste Gesprächsschritt eine einzeilige Bearbeitung statt einer Neuzeichnung:
"Setze Redis oberhalb des Backends und PostgreSQL unterhalb." →
update_element× 2, alles andere bleibt unberührt.
"Stecke nun die gesamte Infrastruktur in eine Box namens AWS." →
group_elements, und nichts bewegt sich.
Related MCP server: Mermaid MCP Server
Architektur
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 UIFünf Ideen halten das Ganze zusammen
1. Der Szenengraph ist das Artefakt, SVG ist nur ein Ausgabeformat.
Alles, was das Modell sendet, wird zu einer Scene validiert und gespeichert. Das Rendern ist eine reine Funktion dieser Szene, sodass dasselbe Diagramm später in einem anderen Thema oder durch ein anderes Backend neu gerendert werden kann, ohne dass das Modell involviert ist.
2. Semantische Elemente werden zu Primitiven kompiliert.
database wird zu einem Pfad, einer Ellipse und zwei Textblöcken. connection wird zu einem Pfad mit einer Markierung. Der Renderer sieht nur die zehn Primitiven – das hält ihn klein, und das Hinzufügen von neuron, decisionTree oder functionPlot später ist eine Erweiterungsdatei in src/semantic/, ohne Änderung der Schema-Union, der Layout-Engine oder des Renderers.
3. Eine Geometrie-Pipeline, zwei Backends.
Die eigentliche Ausgabe des Renderers ist ein SvgNode-Baum, kein String. serialize() wandelt ihn in Markup für die MCP-Tools um; <SceneRenderer> bildet ihn auf React-Elemente für die UI ab. Es gibt keine zweite Implementierung, die abweichen könnte, und kein dangerouslySetInnerHTML irgendwo im Projekt.
4. Fehler werden für ein Modell geschrieben, nicht für eine Logdatei.
{
"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."
}
}Ein Code, nach dem verzweigt werden kann, ein Satz, der das Problem benennt, und ein Hinweis, der die Antwort enthält. Niemals ein Stacktrace.
5. Jede Mutation ist atomar. Eine abgelehnte Bearbeitung hinterlässt die gespeicherte Szene bytegenau so, wie sie war. Ohne das würde ein einziger fehlerhafter Aufruf das Diagramm für den Rest des Gesprächs zerstören.
Abweichungen vom ursprünglich skizzierten Layout
src/layout/ist ein eigenes Modul, getrennt vonsrc/semantic/. Positionierung und Expansion von Bedeutung zu Form sind unterschiedliche Probleme, und die Aufteilung ist es, die das Austauschen von Dagre oder ELK später zu einer Änderung in einer Datei (src/layout/flow.ts) macht – derenFlowItem-in-/out-Schnittstelle bewusst die Form dieser Bibliotheken widerspiegelt.SvgNodesitzt zwischen dem Renderer und seiner Ausgabe (Idee 3 oben), was es ermöglicht, dass die React-Ansicht ohne einen zweiten Renderer und ohne unsichere HTML-Injektion existiert.src/mcp/widget.tsist ein abhängigkeitsfreier Vanilla-Viewer, getrennt von der React-App insrc/ui/. Die ChatGPT-iframe-Ressource muss ein einzelner, in sich geschlossener HTML-String sein, ohne Build-Schritt, der zur Laufzeit veraltet oder fehlen könnte; die React-App ist der lokale Spielplatz. Sie teilen dasselbe Verhalten (Zoom/Pan/Fit/Kopieren/Exportieren) und dieselbe Erlaubnisliste.Auto-Fit ist standardmäßig aktiviert, sodass
width/heightals Hinweise und nicht als harte Leinwand fungieren. Dies beseitigt den häufigsten Fehlermodus – ein Modell wählt eine zu kleine Leinwand und schneidet sein eigenes Diagramm ab.
Installation
git clone <this repo>
cd visual-mcp
npm installErfordert Node 20+ (entwickelt auf Node 22/26).
Entwicklung
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.htmlSchneller End-to-End-Check gegen einen laufenden Server:
npm run dev:http &
npx tsx scripts/smoke-mcp.tsEs spielt die gesamte Zielkonversation nach – baue ein Diagramm ohne Koordinaten, inspiziere es, verschiebe zwei Knoten, verpacke alles in eine Box – und prüft das Ergebnis bei jedem Schritt.
Verfügbare MCP-Tools
Tool | Was es tut | Wann das Modell danach greifen sollte |
| Erstellt und rendert eine ganze Szene in einem Aufruf, gibt eine | Jede Aufforderung, etwas zu zeichnen, visualisieren, diagrammieren, illustrieren oder visuell zu erklären. Der Standard-Einstiegspunkt. |
| Rendert eine gespeicherte Szene erneut. | Nach einer Reihe von Bearbeitungen, um das Ergebnis zu zeigen. |
| Gibt die Szene plus die berechneten Boxen jedes Elements zurück. | Vor dem Bearbeiten – insbesondere für relative Änderungen ("etwas nach rechts"). |
| Fügt ein Element hinzu, optional innerhalb einer Gruppe. | "Füge einen Load Balancer hinzu", "zeichne einen Pfeil von A nach B". |
| Ändert nur die angegebenen Felder; | Jede "ändere das"-Anfrage. Niemals dafür neu zeichnen. |
| Löscht ein Element, kaskadierend seine Verbindungen und Beschriftungen. | "Entferne den Cache". |
| Fasst Elemente der obersten Ebene in einer beschrifteten Box zusammen, ohne etwas zu verschieben. | "Stecke das alles in AWS", "gruppiere diese in eine VPC". |
| Erstellt eine leere Leinwand. | Nur beim schrittweisen Aufbau eines großen Diagramms. |
| Leert eine Szene, behält ihre Leinwand/Thema/Überschrift. | "Weg damit, fangen wir von vorne an". |
| Gibt funktionierende Beispielszenen und den Typenkatalog zurück. | Wenn man unsicher ist, wie man etwas ausdrückt – kopieren und anpassen. |
Jede Toolbeschreibung sagt, was es tut, wann man es verwendet, wann nicht, und was jede Eigenschaft bedeutet, weil ein anderes Modell diese liest und selbstständig entscheidet. Schreibgeschützte Tools tragen readOnlyHint: true und destruktive destructiveHint: true, die Hosts verwenden, um zu entscheiden, was eine Bestätigung erfordert.
Szenen-Schema
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[];
}Jedes Element hat id und type. IDs sind stabil und ermöglichen die konversationelle Bearbeitung.
Primitive – was der Renderer zeichnen kann
circle · ellipse · rectangle · line · arrow · text · polygon · polyline · path ·
group
Semantische Elemente – was das Modell tatsächlich verwenden sollte
Typ | Zweck |
| Beschriftete Box. Zehn Formen ( |
| Verknüpfung nach ID: |
| Beschrifteter Container mit eigenem Layout. Begrenzungen wie "AWS", "VLAN 10". |
| Ein Koordinatensystem und ein Datenrahmen. |
| Markierungen und Linien in Daten-Koordinaten, wenn |
| Beschriftung, die nach ID an ein anderes Element angehängt werden kann und ihm folgt. |
| Domänenvorgaben – ein |
Layout
layout: "auto" (Standard) erstellt einen geschichteten Fluss aus dem Verbindungsgraphen, falls vorhanden, ansonsten eine Zeile. Elemente mit explizitem x/y werden nie bewegt, sodass das Modell einen Knoten verschieben kann, ohne die anderen zu stören. direction steuert, in welche Richtung der Fluss wächst.
Datenrahmen
Ein axis deklariert eine Abbildung von Dateneinheiten zu Pixeln; alles mit frame: "<axis id>" wird in Datenkoordinaten platziert, mit y, das nach oben wächst, wie es sein sollte:
{ "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 }Themen
Vier eingebaute Themen (dark, light, blueprint, paper), jedes eine vollständige Palette plus einen Schriftstapel, der keine externen Schriftarten benötigt. Elemente beziehen sich auf Token – primary, surface, muted, danger – anstatt auf hartcodierte Farben, sodass ein ganzes Diagramm umgestaltet wird, ohne seine Geometrie zu berühren. themeOverrides ändert jeden Token.
Lokales Ausführen
Als Bibliothek, ganz ohne 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" },
],
});Als HTTP-Server
npm run dev:httpRoute | |
| MCP Streamable HTTP-Endpunkt |
| Health-Check |
| Gespeicherte Szenen |
| Eine gerenderte Szene |
| Der interaktive Viewer, eigenständig |
Der Server ist zustandslos: Jede Anfrage erhält einen eigenen McpServer und Transport, und der Szenenspeicher ist der einzige gemeinsame Zustand. Das macht ihn sicher hinter einem Load Balancer oder auf einer serverlosen Plattform, wo zwei Schritte einer Konversation möglicherweise nicht denselben Prozess erreichen.
Als stdio-Server (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"]
}
}
}Verbindung zu ChatGPT
ChatGPT erreicht entfernte MCP-Server über Streamable HTTP an einem öffentlichen HTTPS-Endpunkt, daher muss der Server vom Internet aus erreichbar sein. Zwei Möglichkeiten:
A. Schneller Test mit einem Tunnel
npm run dev:http # http://localhost:3333/mcp
npx localtunnel --port 3333 # or: ngrok http 3333, or cloudflared tunnelB. Bereitstellung mit Docker auf einem VPS
docker-compose.yml startet zwei Container: den MCP-Server auf Port 4000 (nicht ins Internet veröffentlicht) und Caddy, der davor TLS terminiert und das Zertifikat automatisch erneuert.
Dieser VPS hat bereits andere Dienste auf den Ports 80 und 443, daher:
Port | Grund | |
HTTPS / MCP-Endpunkt | 500 | 443 ist belegt |
ACME HTTP-01-Challenge | 90 | 80 ist belegt |
MCP-Server | 4000 | nur intern, nie veröffentlicht |
Der Haken: Let's Encrypt verbindet sich für HTTP-01 immer mit Port 80 – das ist durch RFC 8555 festgelegt und kann nicht konfiguriert werden – und TLS-ALPN ist ebenfalls auf 443 festgelegt. Caddy kann auf 90 hören, aber irgendetwas muss die Anfrage dorthin leiten. Also muss der Dienst, der bereits Port 80 belegt, den Challenge-Pfad an Caddy weiterleiten.
1. Wähle einen öffentlichen Hostnamen. ChatGPT benötigt HTTPS, und eine reine IP kann kein Zertifikat haben. Ohne eine eigene Domain verwende sslip.io – es löst <ip>.sslip.io ohne Registrierung zu dieser IP auf, und Let's Encrypt stellt Zertifikate dafür aus:
curl -4 ifconfig.me # on the VPS -> e.g. 203.0.113.45
# hostname becomes: 203.0.113.45.sslip.io2. Leite die ACME-Challenge vom Port-80-Server weiter. Identifiziere ihn zuerst:
sudo ss -lptn 'sport = :80'nginx – innerhalb des server { listen 80; }-Blocks:
location /.well-known/acme-challenge/ {
proxy_pass http://127.0.0.1:90;
proxy_set_header Host $host;
}Apache – innerhalb des <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 – innerhalb des Site-Blocks, der Port 80 bedient:
handle /.well-known/acme-challenge/* {
reverse_proxy 127.0.0.1:90
}Verwende einen echten Proxy, keine 301-Weiterleitung: Let's Encrypt folgt Weiterleitungen nur zu den Ports 80 und 443, daher würde eine Weiterleitung zu :90 fehlschlagen.
3. Konfiguriere und starte:
cp .env.example .env
# MCP_DOMAIN=203.0.113.45.sslip.io
docker compose up -d --buildWenn der Port-80-Server in einem eigenen Container und nicht auf dem Host läuft, ist 127.0.0.1:90 von dort aus nicht erreichbar – setze MCP_HTTP_BIND=0.0.0.0 in .env und richte den Proxy auf die interne IP des VPS (oder platziere beide Container in einem Docker-Netzwerk).
4. Überprüfe (die erste Anfrage kann einige Sekunden dauern, während das Zertifikat ausgestellt wird):
curl https://$MCP_DOMAIN:500/health # {"status":"ok",...}
docker compose logs caddy | grep -i "certificate obtained"Die MCP-URL lautet dann https://<MCP_DOMAIN>:500/mcp und ist dauerhaft: restart: unless-stopped überlebt Neustarts, und die Zertifikate leben im caddy_data-Volume, sodass Erneuerungen über docker compose down/up hinweg bestehen bleiben. Nur docker compose down -v löscht sie. Behalte die Challenge-Weiterleitung bei – Erneuerungen alle ~60 Tage benötigen sie genauso wie die Erstausstellung.
PUBLIC_URL und ALLOWED_HOSTS werden von Compose aus MCP_DOMAIN und MCP_HTTPS_PORT abgeleitet. Beide müssen den Port enthalten: PUBLIC_URL, weil svgUrl-Links sonst auf 443 zeigen würden, und ALLOWED_HOSTS, weil das SDK den rohen Host-Header – der bei einem nicht standardmäßigen Port <domain>:500 lautet – als exakten String vergleicht.
Wenn du den Port-80-Server nicht anfassen kannst, ist HTTP-01 überhaupt nicht verfügbar. Die Optionen sind eine DNS-01-Challenge (benötigt eine echte Domain bei einem unterstützten DNS-Anbieter – sslip.io hat keine API) oder ein Cloudflare Tunnel, der überhaupt keine eingehenden Ports benötigt.
Ohne 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-mcpRichte dann einen beliebigen Reverse-Proxy auf http://127.0.0.1:4000 aus. Der Container läuft als nicht-root node-Benutzer, hat einen /health-HEALTHCHECK und enthält nur Produktionsabhängigkeiten. Auch verwaltete Plattformen (Fly.io, Railway, Render, Cloud Run) funktionieren – sie injizieren ihren eigenen PORT, den der Server beachtet.
Dann in ChatGPT
Aktiviere den Entwicklermodus. Er ist auf ChatGPT Business, Enterprise und Edu im Web verfügbar. Ein Admin aktiviert ihn unter Workspace-Einstellungen → Berechtigungen & Rollen → Verbundene Daten → Entwicklermodus / Benutzerdefinierte MCP-Connectors erstellen.
Einstellungen → Connectors → Erstellen / Erweitert → Entwicklermodus → Benutzerdefinierten Connector hinzufügen.
Fülle aus:
Name:
Visual MCPMCP-Server-URL:
https://<your-host>/mcpAuthentifizierung:
Keine Authentifizierung(dieser Server wird ohne Authentifizierung ausgeliefert – siehe Sicherheit)
Speichern. ChatGPT ruft sofort
tools/listauf; du solltest die zehn Tools aufgelistet sehen.Aktiviere in einem neuen Chat den Connector und bitte um ein Diagramm.
Der Server registriert auch eine MCP Apps UI-Ressource (ui://visual-mcp/scene.html, text/html;profile=mcp-app), die über _meta.ui.resourceUri und das ChatGPT-Alias _meta["openai/outputTemplate"] an die Rendering-Tools gebunden ist. Wo dies unterstützt wird, erscheint das Diagramm in einem interaktiven Frame mit Zoom, Schwenken, Anpassen, Kopieren und Exportieren; andernfalls geben die Tools das SVG weiterhin in structuredContent zurück, sodass der Server anmutig degradiert.
Beispiele
npm run examples rendert alle fünf nach examples/out/index.html, und list_examples serviert sie dem Modell.
1. Netzwerk – examples/out/network.svg
Domain-Voreinstellungen und automatisches Layout von links nach rechts. computer → switch → router → server, mit VLAN-Beschriftungen auf den Verbindungen. Keine Koordinaten irgendwo in der Quell-Szene.
2. LDA – examples/out/lda.svg
Ein axis-Datenrahmen, zwei gesäte cluster mit weichen Hüllen, eine gestrichelte Entscheidungsgrenze und die LDA-Richtung – alles in Datenkoordinaten, beide Linien auf den Plot beschnitten.
3. Regression – examples/out/regression.svg
Achse, eine scatter-Serie und eine angepasste plotLine mit extend: true, im hellen Thema.
4. Softwarearchitektur – examples/out/architecture.svg
React → REST API → { Redis, PostgreSQL }, mit den beiden Speichern innerhalb einer beschrifteten group ("Data layer"), in die die Verbindungen hineinführen.
5. Binärbaum – examples/out/tree.svg
Sieben kreisförmige Knoten und sechs Verbindungen; das geschichtete Layout mit Flussrichtung down erzeugt den Baum.
Auszuprobierende Prompts in 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].Sicherheit
Das Bedrohungsmodell ist einfach: Alles, was der Server rendert, stammt von einem Sprachmodell, und diese Ausgabe kann selbst Text enthalten, den der Benutzer von woanders eingefügt hat. Daher wird niemals etwas, das vom Modell stammt, als Code behandelt.
Geschlossenes Schema. Nur die vierundzwanzig bekannten Elementtypen werden geparst. Farben müssen einer Hex-/RGB-/HSL-/Schlüsselwort-/Token-Grammatik entsprechen –
url(javascript:…)wird bei der Validierung abgewiesen. Pfaddaten müssen SVG-Pfadbefehlen und Zahlen entsprechen, sonst nichts.Positivliste für Ausgaben. Der Renderer kann nur Tags und Attribute aus zwei expliziten Listen in
src/renderer/svgNode.tsausgeben. Es gibt keinon*, keinhref, keinstyle, keinclass, kein<foreignObject>, kein<script>– das Modell kann sie nicht ausdrücken, und der Serialisierer würde sie ohnehin fallen lassen.Escaping. Textinhalte und Attributwerte werden beim Verlassen XML-escaped.
Kein
dangerouslySetInnerHTML, keineval, keinnew Functionirgendwo im Projekt. Die React-Ansicht baut Elemente aus demSvgNode-Baum; das ChatGPT-Widget parst das SVG und baut es Knoten für Knoten gegen dieselben Positivlisten neu auf, sodass selbst ein kompromittierter Server kein Skript in diesen Frame bringen kann.Begrenzte Eingabe. Elementanzahlen, Zeichenkettenlängen, Punktanzahlen, Pfadlänge und gespeicherte Szenen sind alle begrenzt; Szenen werden nach dem FIFO-Prinzip verdrängt.
Keine Stack-Traces für das Modell. Jeder Handler ist umschlossen; alles Unerwartete wird zu
INTERNAL_ERRORmit einer kurzen Nachricht.
Tests in tests/security.test.tsx bestätigen jeden dieser Punkte.
Nicht enthalten, absichtlich: Authentifizierung. Der Server gibt keine Geheimnisse preis und berührt kein externes System, aber eine öffentliche Bereitstellung ist ein öffentlicher Szenenspeicher. Setze ihn hinter die Authentifizierung deiner Plattform oder füge OAuth über die Auth-Helfer des SDKs hinzu, bevor du ihn anderen als dir selbst zugänglich machst. Setze ALLOWED_HOSTS, um den DNS-Rebinding-Schutz zu aktivieren, wenn er von einem Browser aus erreichbar ist.
Aktuelle Einschränkungen
Textmetriken werden geschätzt, nicht gemessen – es gibt keine Schriftart-Engine auf dem Server. Breiten liegen für die gebündelten serifenlosen Stapel innerhalb weniger Prozent, was für Boxen und Zeilenumbrüche ausreicht, aber eine ungewöhnliche Schriftart oder viel CJK wird etwas locker dimensioniert.
Die Layout-Engine ist bewusst klein. Längster-Pfad-Schichtung mit Rangzentrierung. Sie hat keine Kreuzungsminimierung und keine Überlappungsauflösung, daher erzeugt ein dichter Graph (etwa 25+ Knoten mit vielen Querverbindungen) Kreuzungen, die eine echte Engine vermeiden würde. Die Schnittstelle ist genau aus diesem Grund Dagre-förmig.
Baumlayouts sind nicht kindzentriert; ein Elternteil sitzt in der Mitte seines Ranges, nicht über dem Mittelpunkt seiner Kinder.
Das JSON-Schema von
render_diagramist etwa 50 KB (~12k Tokens), weil es das gesamte Elementvokabular lehrt. Die anderen neun Tools summieren sich auf ~5 KB. Das ist ein bewusster Kompromiss: Das Modell erhält feldweise Dokumentation und benötigt selten eine Reparaturrunde.Innerhalb einer Gruppe mit automatischem Layout werden explizite
x/yder Kinder ignoriert – das Layout gewinnt. Verwendelayout: "manual"auf der Gruppe, um Kinder selbst zu positionieren.Der Speicher ist im Arbeitsspeicher. Szenen überleben keinen Neustart, und bei mehreren Replikaten lebt eine Szene auf der Instanz, die sie erstellt hat. Das
SceneStore-Interface existiert, sodass dies eine auszutauschende Klasse ist.Statische Ausgabe. Noch keine Animation, kein 3D, kein Mathe-Ausdrucksparser – siehe unten.
Fahrplan
Als Nächstes
Persistenter
SceneStore(zuerst SQLite) – das Interface ist bereits vorhanden.Rückgängig/Wiederholen. Jede Mutation wird bereits als
SceneMutationaufgezeichnet; es ist eine Frage der Speicherung der Umkehrung.Dagre oder ELK hinter
src/layout/flow.tsfür dichte Graphen, mit der kleinen Engine als Standard.Kindzentriertes Baumlayout.
Mathe – der axis-Datenrahmen ist die Grundlage; jeder davon ist ein Expander in src/semantic/, ohne Renderer-Änderung:
functionPlot ({ "expression": "x^2", "domain": [-5, 5] }), vector, matrix, plane, distribution, projection, decisionBoundary und regressionLine als benannte Aliase von plotLine.
Diagrammvokabular – neuron, neuralNetwork, decisionTree, sequenceDiagram, stateMachine, gantt, swimlane.
Animation – { "animation": { "type": "flow", "duration": 1200 } } auf einer Verbindung, ausgegeben als SVG SMIL oder CSS, sodass es deklarativ bleibt und keine Laufzeit benötigt. Pakete, die sich entlang einer Verbindung bewegen, eine Anfrage, die durch eine Pipeline reist, ein Algorithmus, der durch eine Struktur schreitet.
Andere Renderer – die Auflösungspipeline endet bereits in einem backend-agnostischen Baum. Eine Scene mit kind: "3d" und { "type": "sphere", "position": [0, 1, 0] } würde ein Three.js-Backend anstelle des SVG-Backends auswählen; ein Canvas-Backend würde sehr große Streudiagramme bedienen. Keine Änderung an der MCP-Schicht.
Lizenz
MIT
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityBmaintenanceA Model Context Protocol server that enables LLMs to create, modify, and manipulate Excalidraw diagrams through a structured API.111,7302,274MIT
- -license-quality-maintenanceA server that implements the Model Context Protocol (MCP), providing an interface for LLM applications to generate mermaid.js visualizations and diagrams.
- AlicenseAqualityDmaintenanceA Model Context Protocol (MCP) server designed to easily dump your codebase context into Large Language Models (LLMs).163Apache 2.0
- AlicenseBqualityDmaintenanceA Model Context Protocol server that enables LLMs to create, modify and manipulate Excalidraw diagrams through a structured API, supporting element creation, styling, organization, and scene management.12797MIT
Related MCP Connectors
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
A Model Context Protocol server for Wix AI tools
MCP (Model Context Protocol) server for Appwrite
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/daniel69zz/visual_draw_mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server