Skip to main content
Glama
harezadmm
by harezadmm
README.md
# bizagi-mcp

**Turn a description of a process into a BPMN 2.0 diagram that opens cleanly in Bizagi Modeler.**

An [MCP](https://modelcontextprotocol.io) server that generates, reads, audits and previews
BPMN 2.0 diagrams — and drives the Bizagi Modeler desktop app on Windows.

![An auto-laid-out purchase request process](docs/example-purchase-request.png)

*Generated from a 60-line JSON spec. Every coordinate above was computed, not placed by hand.*

---

## Why this exists

Bizagi Modeler has no scripting API. The one integration path it does support is the open
**BPMN 2.0 XML** format, through its Export / Import tab.

But there is a catch that makes naive generation useless: **Bizagi imports the coordinates
written in the file verbatim.** It does not lay out a diagram for you. Emit a structurally
perfect BPMN file without geometry and it opens as a pile of boxes stacked on the origin.

So the hard part of this server is not the XML. It is the layout.

---

## What it does

| Tool | What it does |
| --- | --- |
| `get_spec_reference` | The spec format: every node type, field and rule |
| `create_process` | Description → a `.bpmn` file ready to import, coordinates computed |
| `update_process` | Edit an existing `.bpmn` (add/change/remove nodes and flows), re-laid out |
| `read_process` | Parse a `.bpmn` → structured JSON, a readable walk-through, or an editable spec |
| `list_processes` | Scan a folder and summarise each BPMN file |
| `validate_process` | Audit against BPMN 2.0 rules and modelling conventions, with a fix for each finding |
| `render_preview` | Render to SVG — check the result without opening Bizagi |
| `export_documentation` | Process documentation as Markdown (outline + audit) |
| `bizagi_status` | Whether Bizagi Modeler can be driven from here |
| `bizagi_open` | Launch Bizagi Modeler, optionally with a file |
| `bizagi_import_bpmn` | Drive Export / Import ▸ BPMN, and verify that it landed |
| `bizagi_export_bpmn` | Drive Export ▸ BPMN for the open diagram |

The first eight are pure Python and run on any OS, with or without Bizagi installed.
Only the four `bizagi_*` tools need Windows.

---

## The layout engine

A lane-aware layered layout, in the order it runs:

1. **Break cycles** so the graph can be layered at all
2. **Longest-path layering** → each node's horizontal column
3. **Barycenter ordering** per (column, lane) → fewer crossing lines
4. **Adaptive lane heights**, sized to the tallest cell each band holds
5. **Reserved strips** — a bypass band along the top of any lane carrying a
   column-skipping branch, and a channel strip at the bottom for loop-backs
6. **Orthogonal routing** that goes *around* obstacles rather than through them
7. **Label separation** as a final pass

### What it guarantees

These are not aspirations. Each one is a test that fails when the rule is removed:

- No two shapes overlap
- No edge is drawn through a shape that is not its own endpoint
- Every element sits inside its pool
- Message flows run in the empty corridor **between** pools, never horizontally through one
- Each message flow gets its own line in that corridor, and the corridor is sized
  from how many flows cross it — so their labels do not stack
- Loop-backs each get their own channel in a strip reserved while lanes are sized
- A branch that skips columns detours inside its own lane, over the activities it skips
- A gateway's branches leave from visibly different points, so a two-way split
  does not read as a single arrow
- Boundary-event flows leave downwards, never back up through the host activity
- Annotations and data stores sit beside what they describe — or, when they have no
  association, inside the pool they declare rather than off the canvas
- No label is written over another label or over a shape

### Design notes

A few decisions that are easy to get wrong:

- **A label is as wide as its text.** Reserving a flat box for every label makes
  collisions between the long ones invisible to anything that measures the reserved box.
- **Reserved space must be held out of centring.** Grow a lane to make room for a
  channel and then centre the shapes in it, and half the new space is handed back as
  padding above — the channel ends up too thin to use.
- **A detour belongs in the gaps between shapes, not around all of them.** Routing over
  or under everything lands the line outside the pool, and the verticals that reach it
  then cross every lane on the way.
- **A data store can be associated with many activities but sits beside one.** Placing
  it once per association leaves holes in the lanes where the earlier placements were.

---

## Install

```bash
pip install -e .
```

For the Windows desktop tools:

```bash
pip install -e ".[desktop]"
```

Python ≥ 3.10.

### Register with Claude

`claude_desktop_config.json` (Windows: `%APPDATA%\Claude\claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "bizagi-modeler": {
      "command": "bizagi-mcp",
      "env": {
        "BIZAGI_MCP_ROOT": "C:\\Users\\you\\Documents\\Bizagi"
      }
    }
  }
}
```

If `bizagi-mcp` is not on PATH:

```json
{
  "mcpServers": {
    "bizagi-modeler": {
      "command": "python",
      "args": ["-m", "bizagi_mcp.server"],
      "env": { "BIZAGI_MCP_ROOT": "C:\\Users\\you\\Documents\\Bizagi" }
    }
  }
}
```

For Claude Code: `claude mcp add bizagi-modeler -- bizagi-mcp`

### Environment variables

| Variable | What it does |
| --- | --- |
| `BIZAGI_MCP_ROOT` | Confine every file read and write to this folder. **Strongly recommended.** |
| `BIZAGI_MODELER_PATH` | Full path to `BizagiModeler.exe` or `BizAgiMC.exe` when it is not found automatically |

---

## Usage

### Generate a diagram

> "Model a leave request: the employee submits it, the manager approves or rejects it,
> HR records the outcome. Save it to `D:\Processes\leave.bpmn`."

Then in Bizagi Modeler: **Export / Import ▸ Import ▸ BPMN**.

### Analyse an existing model

Export from Bizagi first (**Export / Import ▸ Export ▸ BPMN**), then:

> "Read `D:\Processes\purchasing.bpmn`, walk me through it, and tell me what is wrong with it."

### Example

See `examples/purchase_request.json` (the spec), `.bpmn` (generated) and `.svg` (preview).

---

## Validation rules

**Structure** (`BPMN001`–`BPMN020`, severity `error` / `warning`)

Missing start or end events · unreachable elements · dead ends · sequence flows crossing
pools · message flows inside one pool · gateways branching without conditions ·
event-based gateway targets · implicit split and merge · boundary events on
non-activities · duplicate ids · a default flow that also carries a condition ·
one-in-one-out gateways.

**Conventions** (`BP001`–`BP017`, severity `warning` / `info`)

Activity naming (verb + object) · gateways not phrased as questions · unlabelled
branches · documentation coverage · pools without lanes · empty lanes · diagram size ·
duplicate names · pools that never exchange messages.

Every finding names the offending element and the concrete step to fix it.

---

## Driving the desktop app

`bizagi_open` is the dependable path: Modeler takes a file as a command line argument,
so no menu has to be driven.

`bizagi_import_bpmn` drives the ribbon, and is honest about it:

- It claims the foreground and **verifies** it got there. Windows refuses
  `SetForegroundWindow` to a process that does not own the foreground, and `set_focus()`
  returns as if it worked — clicking on regardless sends a real mouse click into whatever
  the user is working in.
- It counts diagram tabs before and after, and reports `imported: true` / `false` from
  that evidence rather than from hope.
- Both counts are taken with the window raised, because a window that is behind can hand
  back an incomplete accessibility tree.

### There is no background mode

Import cannot run while the machine is used for something else. Three routes were tested
against Modeler 4.3.0.008 and all three are closed:

| Route | Result |
| --- | --- |
| UI Automation `Invoke` pattern | Ribbon tabs expose no patterns at all |
| `PostMessage` mouse messages | Ignored, across every candidate window handle |
| `BizAgiMC.exe file.bpmn` | Exits 0 without importing anything |

The ribbon only responds to real mouse input on a focused window. For unattended runs,
give Bizagi its own Windows session or VM. If you want that recorded so nobody retries
it: this table is the record.

---

## Security

- Paths are fully resolved (`~`, `..`, symlinks) **before** being checked, then confined
  to `BIZAGI_MCP_ROOT` when it is set
- XML parsing goes through `defusedxml` when available (XXE, billion laughs)
- Files are never overwritten without `overwrite=true`
- Bizagi is launched with an argument list and no shell, so a filename can never become
  a command
- Every error comes back as data (`{"ok": false, ...}`), never a traceback

---

## Tests

```bash
pip install -e ".[dev]"
pytest -q
```

72 tests: spec normalisation, XSD element ordering, BPMNDI completeness, every layout
guarantee listed above, label collisions, round-trips, each validation rule, path
traversal, ribbon button selection, foreground verification, and the error contract of
every tool.

---

## Known limitations

- **`.bpm` is not read.** It is Bizagi's proprietary format; export to BPMN first.
  `list_processes` still lists `.bpm` files and flags them.
- **Desktop control is Windows-only** and needs `pywinauto`.
- **Diagrams are generated one level deep.** A sub-process appears as a collapsed shape;
  its contents are not generated.
- **Layout tidiness is guaranteed for the geometry written to the file.** Bizagi places
  node names by its own rules, which the diagram interchange section does not control.

## License

MIT — see [LICENSE](LICENSE).

TDQS

A4.4/5.0

Scored across 12 tools

Disambiguation5/5

Each tool targets a distinct action: file discovery, spec reference, create, update, read, validate, preview, documentation, and Bizagi desktop automation. The only mild overlap is preview capability between create_process and render_preview, but their outputs and intended use are clearly differentiated.

Naming Consistency4/5

Most tools follow a clear verb_noun pattern, and the desktop automation tools consistently share the bizagi_ prefix. The minor deviation is bizagi_status, which is a noun phrase rather than verb-first, and get_spec_reference uses get while similar operations use read; still, the overall pattern is predictable.

Tool Count5/5

Twelve tools is well-scoped for a BPMN modeling server. Each tool covers a meaningful part of the workflow without unnecessary redundancy, and the count is comfortably within the typical 3-15 range.

Completeness5/5

The toolset covers the full modeling lifecycle: discovery, creation, editing, reading, validation, preview, documentation, and desktop import/export. The only noted limitation—reading proprietary .bpm files—is documented with a practical workaround rather than an untooled dead end.

Maintenance

ActivityMaintained
ResponsivenessNo issues