vp-online-mcp
v2.0.0
Published
MCP server that builds native, editable Visual Paradigm Online diagrams (UML, ER, BPMN, DFD, flowcharts...) in a single tool call
Maintainers
Readme
vp-online-mcp
English · Español
An MCP server that lets an AI agent (Claude Code, Claude Desktop, Cursor, VS Code or any MCP client) draw native, editable diagrams in Visual Paradigm Online: class, use case, activity, sequence, state, component, deployment, package, ER, DFD, BPMN, flowcharts, org charts, mind maps, and any other shape in VP's library. A whole diagram is one tool call.
What it creates is the same thing you would get drawing by hand in VP: real classes with attributes and operations, associations with multiplicities and roles, ER tables with PK/FK columns, ordered sequence messages, BPMN lanes. Everything lives in VP's model, stays editable in VP, and is saved to your VP cloud.

Unofficial project, not affiliated with or endorsed by Visual Paradigm. It drives the VP Online web editor in a browser with your own account; use it according to VP's terms of service.
Contents
- Quick start
- How the agent works
- Tools
vp_buildconventions- Diagram types and examples
- Design: how it saves tokens
- Architecture
- Configuration
- Troubleshooting
- Known limitations
- Development and tests
Quick start
Requirements: Node.js 20+, Google Chrome or Microsoft Edge, and a Visual Paradigm Online account (needed to save).
1. Add the server to your MCP client
Claude Code
claude mcp add vp-online -s user -- npx -y vp-online-mcpOn Windows, wrap npx with cmd /c:
claude mcp add vp-online -s user -- cmd /c npx -y vp-online-mcpClaude Desktop (claude_desktop_config.json), Cursor (~/.cursor/mcp.json) and most
other clients:
{
"mcpServers": {
"vp-online": {
"command": "npx",
"args": ["-y", "vp-online-mcp"]
}
}
}On Windows use "command": "cmd" and "args": ["/c", "npx", "-y", "vp-online-mcp"].
VS Code (.vscode/mcp.json):
{
"servers": {
"vp-online": { "type": "stdio", "command": "npx", "args": ["-y", "vp-online-mcp"] }
}
}Latest commit from GitHub instead of npm: replace vp-online-mcp with
github:ibsorn/vp-online-mcp (the first start clones and installs it, which takes longer).
From a clone (for development): git clone, npm install, then point the client at
node /path/to/vp-online-mcp/server.js.
2. Log in once
The first tool call opens a dedicated Chrome window with its own profile, separate from your
everyday browser. Log in to Visual Paradigm Online there once; the session is kept in
~/.vp-online-mcp/chrome-profile.
3. Ask for diagrams
"Create in VP the class diagram of a library system: User, Member, Librarian, BookCopy and Loan with their attributes, inheritance and associations with multiplicities. Then save it as 'Library model'."
Without a session you can still build diagrams, but not save them: vp_open warns
NOT SIGNED IN.
How the agent works
vp_open {type} → vp_build {elements, connectors} → vp_inspect → vp_save {name}
(whole diagram, 1 call) (verify) (VP cloud)- Later changes:
vp_editwith many operations in one call. - To look at the result:
vp_screenshot {path}writes a PNG and costs no image tokens. Withoutpathit returns the image. - The conventions reach the model once, in the server
instructions; tool descriptions are one line each.
Tools
| Tool | What it does | MCP annotations |
|---|---|---|
| vp_open {type?, url?} | Opens a new diagram (type) or an existing one (url). No arguments: describes the current one. Returns the palette ids. | non-destructive |
| vp_shapes {query?, limit?} | No query: the diagram's palette. With query: searches all of VP's shape library; results are usable in vp_build. | read-only |
| vp_build {elements?, connectors?, layout?, columns?, clear?} | Creates many elements and connectors at once. If one item fails it carries on and reports it. | destructive (because of clear) |
| vp_edit {ops} | Batched changes (see the next table). | destructive |
| vp_inspect {ref?, filter?, detail?, limit?} | Compact listing of the diagram. | read-only |
| vp_save {name?} | Saves to the VP cloud. On an already saved diagram, a different name saves a copy. | non-destructive, idempotent |
| vp_screenshot {path?, ref?, scale?} | Image cropped to the content, or to one element with ref. | read-only |
| vp_eval {code} | Escape hatch: runs JS in the editor with an api object. | destructive |
vp_edit operations
| op | Fields | Effect |
|---|---|---|
| label | ref, text | Renames an element or connector. |
| move | ref, x, y | Moves the element. |
| resize | ref, w, h | Resizes it. |
| rows | ref, rows, rowAction? | Adds rows (attributes, operations, columns…). |
| removeRows | ref, match? (regex) | Removes rows; without match, all of them. |
| ends | ref, mult?, roles? | Multiplicities and roles [from, to] of a connector. |
| style | ref, style | mxGraph style, e.g. fillColor=#FFF2CC;. |
| delete | ref | Deletes the element and its connectors. |
| add | element fields | Adds an element. |
| connect | connector fields | Adds a connector. |
| layout | kind | Arranges the diagram: grid, hierarchical, horizontal, organic or tree. The hierarchical ones route the connectors; the others clear their waypoints. |
| fit | ref | Fits the size to the text. |
vp_inspect format
"Untitled" ClassDiagram | 8 elements, 7 connectors | unsaved
#1 Class "User" @60,40 252x91 [-id : String; -fullName : String; -failedLogins : int; +login(id : String, pwd : String) : boolean]
#7 Interface "Authenticable" @460,40 252x58 [+login(id : String, pwd : String) : boolean]
#10 Generalization Member -> User
#12 Association Member{0..1} -> BookCopy{0..1} "holds"
#15 Association BookCopy{1,role=copy} -> Loan{0..*,role=loans} "lent in"#idis a short id that every tool accepts asref. Keys and labels work too.- The type shown is the same palette id
vp_builduses. - Connectors are listed in the direction they were created.
detail:"brief"drops coordinates and summarises rows as(9 rows).filterandrefnarrow the output.limitcaps the number of lines (150 by default) and says how to narrow down when it truncates.
vp_build conventions
Element: {shape, label?, key?, x?, y?, w?, h?, parent?, rows?, rowAction?, style?}
shapeis the palette id, e.g.Class,Actor,UseCase,System,Entity,DeviceNode,ActionorLifeline. Seevp_openorvp_shapes.keyis the namefrom,toandparentrefer to. Without it, refer to the label.- Position: without
xandy, the element is auto-placed on a grid without overlaps. With aparentit is placed inside the container, which grows to fit. Coordinates are pixels; a child's are relative to its parent. rows: the server decides which compartment each row goes to:- In a class or interface, a row with
(is an operation; the rest are attributes. - In ER, a row is
"name type", optionally prefixed withPK,FKorPK,FK. - Other shapes use
rowAction(addTrigger,addProcedure,addClause…); if it is missing, the error lists the options. - A row can also be
{text, action?, set?}.setwrites model XML attributes, e.g.{"nullable":"false"}.
- In a class or interface, a row with
- Activity swimlanes: in
VerticalSwimlaneandHorizontalSwimlane,rowsare the partition names. The two template partitions are renamed, extra ones removed, and each additional name adds a partition (a column inVerticalSwimlane). VP only adds vertical partitions to aHorizontalSwimlane, which makes a grid: for N lanes useVerticalSwimlane. - Attached shapes (
Port,InputPin,OutputPin,ActivityParameterNode,Lane) need aparent: ports and pins go on the parent's border, lanes stack inside the pool. label: ""clears a default name, such as the text "DecisionNode".
Connector: {shape, from, to, label?, mult?, roles?, y?, points?, key?, style?}
- Direction: the arrowhead is always at
to.- Generalization:
fromis the subclass,tothe superclass. - Realization:
fromis the implementing class. - Include and Extend:
fromis the base use case.
- Generalization:
- In Aggregation and Composition the diamond is at
from(the whole). multandrolesare[from, to], e.g."mult": ["1", "0..*"].- Sequence: messages stack top-down in the order given;
yplaces one explicitly.SelfMessagedraws a loop with its label beside it, and lifelines grow as needed. pointsare waypoints[[x,y],…].- Two connectors between the same elements are fanned out automatically so they do not overlap
(not for sequence messages or connectors with
points). - Connector texts are kept readable: the name sits beside the line (above it when horizontal), and each end's multiplicity and role go on opposite sides of the line. Texts you moved by hand are left alone.
Errors are actionable, for example:
unknown shape "Clas". Did you mean: Class?"Solo" is ambiguous (#3, #4): use one of these #idsPort must be attached to a parent element (set parent)
Minimal example (a class diagram in one call):
{
"elements": [
{"shape": "Class", "label": "BookCopy", "rows": ["-barcode : String", "-price : float"]},
{"shape": "Class", "label": "Loan", "rows": ["-loanId : int", "+close() : void"]}
],
"connectors": [
{"shape": "Association", "from": "BookCopy", "to": "Loan", "label": "lent in", "mult": ["1", "0..*"]}
]
}Diagram types and examples
Each type has a complete, tested example in examples/; the e2e suite runs
exactly those files.
| type | Key shapes | Key connectors | Example |
|---|---|---|---|
| ClassDiagram | Class, Interface, Enumeration, Package, Note | Generalization, Realization, Association, Aggregation, Composition, Dependency, Usage | class.json |
| UseCaseDiagram | Actor, UseCase, System | Association, Include, Extend, Generalization | usecase.json |
| ActivityDiagram | InitialNode, Action, DecisionNode, MergeNode, ForkNode, JoinNode, ActivityFinalNode, InputPin/OutputPin, VerticalSwimlane | ControlFlow, ObjectFlow | activity.json |
| SequenceDiagram | Actor, Lifeline, BoundaryLifeline, ControlLifeline, EntityLifeline, LoopCombinedFragment | Message, ReplyMessage, SelfMessage, CreateMessage | sequence.json |
| StateMachineDiagram | InitialPseudoState, State, Choice, FinalState | Transition | state.json |
| ComponentDiagram | Component, Interface, Port | Usage, Realization, Dependency | component.json |
| DeploymentDiagram | Node, DeviceNode, ExecutionEnvironmentNode, Artifact, Component | Link, Dependency, Deployment | deployment.json |
| PackageDiagram | Package, Subsystem | Dependency, Import, Access, Merge | package.json |
| ERDiagram | Entity, View, Triggers, StoredProcedures | OnetoOneRelationship, OnetoManyRelationship, ManytoManyRelationship | er.json |
| DataFlowDiagram | Process, ExternalEntity, DataStore | DataFlow, BidirectionalDataFlow | dfd.json |
| BusinessProcessDiagram | HorizontalPool, Lane, StartEvent, Task, UserTask, gateways, EndEvent | SequenceFlow, MessageFlow | bpmn.json |
| Flowchart | Start, Process, Decision, Data, Terminator… | FlowLine | flowchart.json |
| OrganizationChart | Unit | Line | orgchart.json |
| MindMapDiagram | Node | Branch | mindmap.json |
Any other VP diagram type opens with its type too, and vp_shapes {query} finds any shape in
its library.
| Sequence | BPMN |
|---|---|
|
|
|
Design: how it saves tokens
The design follows the practices published by Anthropic and the MCP specification, and what the most used MCP servers do (sources).
| Practice | How it is applied |
|---|---|
| Few tools with distinct purposes that cover whole workflows | 8 tools instead of one per action. vp_build creates a whole diagram in one call. vp_open replaces three tools (new, open, status) and vp_shapes two (palette, search). |
| Shared context once | Conventions live in the server instructions; tool descriptions are one line. |
| Small, flat schemas | One rows field instead of attributes, operations, columns and members. mult and roles as [from, to]. No $schema or default metadata in the listing; annotations are sent only when they differ from the defaults. |
| Compact, meaningful responses | Short ids (#12) and connectors with readable names. vp_build returns one line per group and never echoes the diagram. |
| Selectable response format | vp_inspect detail:"brief", filter, ref and limit; when output is truncated it says how to narrow it. |
| Actionable errors | "Did you mean" suggestions, the list of #ids on ambiguity, missing fields and the valid row action. |
| Images only when needed | vp_screenshot {path} writes the PNG and returns only the path. |
| "Code mode" escape hatch | vp_eval filters or aggregates inside the page and returns only the result. |
| Robustness | Calls run one at a time with timeouts, retry if VP reloads the page, and an expired session is detected. |
Fixed cost measured with npm run measure: 8 tools + instructions ≈ 1,600 tokens.
Measured performance:
| Case | Time | |---|---| | Class diagram (8 classes, 7 relationships) | ~0.6 s | | 40 classes, 320 rows, 45 relationships (60 multiplicities) | ~5–12 s depending on machine load |
How: each build phase runs in one model transaction, rendering and the format panel are paused while working, and rows are written without going through the inline text editor.
Architecture
server.js MCP over stdio: 8 tools, instructions, queue, timeouts, errors
lib/browser.js Dedicated Chrome (own profile, CDP on port 9333) that survives MCP restarts
lib/vp.js Tab lifecycle, injection, workspace, save, screenshots
lib/page-api.js API injected into the VP editor (mxGraph); does all the work
examples/ One example diagram per type (also the e2e test data)
test/ e2e.js (acceptance suite), smoke.js (offline, CI), measure.js, client.js
scripts/eval.js Debug helper: evaluates JS in the editor tabWhy the result is native: page-api.js uses VP's own code paths instead of drawing loose cells:
| To… | It uses… |
|---|---|
| Create shapes | Each palette item's mxDragSource.drop() (like dragging it). |
| Create connectors and attached shapes | The palette template (getCell()) plus connectCell. |
| Create rows | The "Add X" methods behind VP's context menu. |
| Rename | graph.labelChanged. |
Resilient to VP updates: VP's code is minified, so the server never hard-codes an internal name:
EditorUiandGraphinstances are captured on the fly.- Palette metadata is recognised by its shape.
- "Add X" methods are discovered by reading the menu code (
mxResources.get("addAttribute")…). - Each cell's type is read from
origin.paletteItemUiId, which VP stores in the model.
Configuration
| Variable | Default | Use |
|---|---|---|
| CHROME_PATH | auto-detected | Path to Chrome or Edge. |
| VP_MCP_PORT | 9333 | CDP port of the dedicated Chrome. |
| VP_MCP_PROFILE | ~/.vp-online-mcp/chrome-profile | Profile that keeps the VP session. |
| VP_WORKSPACE | auto-detected | VP workspace id (the <ws> in online.visual-paradigm.com/w/<ws>/). Remembered in ~/.vp-online-mcp/state.json. |
| VP_MCP_HEADLESS=1 | off | Chrome without a window. Only useful once the session is logged in. |
Troubleshooting
| Symptom | Fix |
|---|---|
| NOT SIGNED IN, or vp_save says there is no session | The VP session expired. Log in again in the MCP Chrome window and repeat vp_open. |
| No diagram is open | Call vp_open {type} or vp_open {url}. |
| unknown shape "X" | Use one of the ids the error suggests, or search with vp_shapes {query}. |
| The Chrome window was closed | The next call reopens it with the same session. |
| Chrome not found | Install Chrome or Edge, or set CHROME_PATH. |
| Could not attach to the VP editor | Reload the tab. If it persists, VP changed its internals: please open an issue. |
| A very large vp_build times out (5 min) | Split it into several calls. vp_inspect shows what was already applied. |
Known limitations
- Saving needs a session. VP expires sessions after some hours; log in again when told.
- Sequence diagrams: messages do not create activation bars. It is still valid UML; add them in VP if you want them.
- Auto-layout uses mxGraph's algorithms and does not route lines around obstacles. For polished
diagrams give explicit
x/y. - Shape search: result ids (
Decision10…) are generated by VP and may change.vp_buildalso accepts the title, e.g."Decision". - Unofficial: it relies on VP Online's web editor. A VP update can break something until this project adapts; the e2e suite exists to detect it fast.
Development and tests
npm run check # offline smoke test (no browser): tools, schemas, examples, metadata
npm test # full e2e suite against VP Online, without saving (~2–5 min)
npm run test:save # also save, re-save, save a copy and reopen (creates 2 diagrams in your cloud)
npm test -- class er # only those suites
npm run measure # token cost of the tool definitionsThe e2e suite (test/e2e.js) drives the real server over stdio against VP Online and checks
concrete results: the 14 diagram types, every vp_edit operation, vp_inspect modes and
screenshots, the five auto-layouts without overlaps, errors and their messages, shape search,
concurrent calls, save/copy/reopen/edit after reload, and a stress case (40 classes, 320 rows,
45 relationships). Last result: 220/220 including saving. Screenshots of every diagram are
written to test/out/ for visual review.
See CONTRIBUTING.md, SECURITY.md and CHANGELOG.md.
Sources
- Anthropic, Writing effective tools for agents: consolidating tools, concise or detailed responses, meaningful ids, actionable errors, pagination and truncation.
- Anthropic, Code execution with MCP: progressive disclosure and filtering data inside the execution environment.
- MCP specification: Tools:
annotations and
isErrorresults. - bump.sh, 4 rules to build an efficient MCP server.
- Cloudflare, Code Mode: a small search/execute surface instead of thousands of tools.
- Playwright MCP, snapshots: structured text instead of screenshots.
License
MIT. Visual Paradigm is a trademark of its respective owner.
