Skip to main content
Glama
README.md
# visio-mcp

An MCP server that drives **the Microsoft Visio window you already have open**.

It attaches to the running Visio instance through the COM running-object table,
so the drawing on your screen is the drawing the model sees. It never launches a
second, hidden copy of Visio and it never opens files behind your back — whatever
is in front of you is what gets read and edited, live, with each tool call
landing as a single Ctrl+Z step.

```
you: "the approval box should say 'Legal review' and hang off the risk step"
     -> visio_list_shapes, visio_render_page, visio_set_shape_text, visio_connect_shapes
```

## Requirements

- Windows, with Microsoft Visio installed (desktop Visio — the web app has no COM API)
- Python 3.10 or newer
- `pywin32`, installed automatically on Windows

The server itself must run on the same Windows machine as Visio. It can't reach a
Visio running on another host, in a VM, or in Visio for the web.

## Install

```powershell
git clone https://github.com/isiec9ai/MCP.git visio-mcp
cd visio-mcp
py -m venv .venv
.venv\Scripts\pip install -e .
```

## Point a client at it

Open Visio with the drawing you care about, then add the server.

**Claude Code**

```powershell
claude mcp add visio -- C:\path\to\visio-mcp\.venv\Scripts\visio-mcp.exe
```

**Claude Desktop** — in `%APPDATA%\Claude\claude_desktop_config.json`
(see `claude_desktop_config.example.json`):

```json
{
  "mcpServers": {
    "visio": {
      "command": "C:\\path\\to\\visio-mcp\\.venv\\Scripts\\visio-mcp.exe",
      "args": []
    }
  }
}
```

Ask for `visio_status` first; it tells you which instance is attached and what it
has open.

## Tools

Everything defaults to the document and page you are looking at. Pass `document`
(file name or 1-based index) and `page` (name or 1-based index) to work
elsewhere. Coordinates and sizes are **inches from the bottom-left of the page**,
and a shape's `x`/`y` is its centre — matching Visio's own ShapeSheet.

### Reading

| Tool | What it does |
| --- | --- |
| `visio_status` | Which Visio instance is attached, and what it has open |
| `visio_list_documents` | Open drawings (add `include_stencils` for the rest) |
| `visio_list_pages` | Pages, their size and shape counts |
| `visio_list_shapes` | Shapes with the **ids every editing tool needs**, text, master, geometry |
| `visio_get_shape` | One shape in full: Shape Data, user cells, layers, hyperlinks, neighbours |
| `visio_list_connections` | The page as a graph, including connectors dangling at one end |
| `visio_search_text` | Find shapes by text across every page |
| `visio_list_masters` | Masters available to drop, from the drawing and open stencils |
| `visio_render_page` | A PNG of the page, returned inline so the model can *look* at it |
| `visio_export_page` | Write a page to .png/.jpg/.svg/.emf/... on disk |
| `visio_export_pdf` | Export the document to PDF |

### Editing

| Tool | What it does |
| --- | --- |
| `visio_set_shape_text` | Replace a shape's text |
| `visio_add_shape` | Drop a master, or draw a rectangle/ellipse/line, and get its new id |
| `visio_connect_shapes` | Glue a dynamic connector between two shapes |
| `visio_move_shape` | Move, resize or rotate — only the values you pass change |
| `visio_delete_shape` | Delete a shape |
| `visio_add_page` | Add a page |
| `visio_set_shape_data` | Set a Shape Data field, creating the row if needed |
| `visio_replace_text` | Find and replace across shapes |
| `visio_select_shapes` | Select shapes in the window, to show you what it means |
| `visio_save` | Write to disk (edits are in memory until you ask) |
| `visio_undo` | Undo, exactly as Ctrl+Z would |

## Staying in control

- **Nothing is written to disk** unless `visio_save` is called. Close without
  saving and every edit is gone.
- **Each tool call is one undo step.** Writes run inside a Visio undo scope, so a
  single Ctrl+Z reverses a whole `visio_add_shape`, not half of it.
- **`--read-only` publishes only the inspection tools.** The write tools are not
  registered at all, so a client cannot call them even by name:

  ```powershell
  visio-mcp --read-only          # or set VISIO_MCP_READ_ONLY=1
  ```

- `visio_undo` pops whatever is on top of Visio's undo stack, which may be *your*
  last edit rather than the model's. Prefer Ctrl+Z yourself when it matters.

## Trying it without Visio

`--fake` swaps in an in-memory sample drawing — a three-box flowchart — so you
can wire the server into a client and explore every tool on any OS:

```bash
visio-mcp --fake
```

## Troubleshooting

**"No running Visio instance was found"**

- Visio has to be *running*, with at least one drawing open.
- Privilege levels have to match. A server started from an elevated terminal
  cannot see a normally-launched Visio, and vice versa — the running-object table
  is per integrity level. Start both the same way.
- Visio for the web and Visio Viewer expose no automation API.

**It attached to the wrong instance.** With several Visio processes running, the
running-object table hands out whichever registered first. Close the ones you
don't want, or use `visio_list_documents` to confirm before editing.

**A tool reports the connection was lost.** Visio was closed or restarted. The
server re-attaches on the next call; run `visio_status` to confirm.

**`visio_add_shape` can't find a master.** Run `visio_list_masters` to see what
the drawing and its open stencils actually offer, or pass `stencil` with a name
Visio knows (`BASIC_U.VSSX`) or a full path to a `.vssx`.

## Development

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

The suite runs anywhere: `src/visio_mcp/fake_backend.py` implements the same
contract as the COM backend (`src/visio_mcp/backend.py` defines it), so the whole
tool surface is exercised without Windows. The COM layer itself needs a real
Visio to test against.

Layout:

| File | Role |
| --- | --- |
| `backend.py` | The contract both backends implement |
| `com_backend.py` | The live Visio instance, over COM |
| `fake_backend.py` | In-memory stand-in for tests and `--fake` |
| `session.py` | Serialises calls onto one COM-initialised thread |
| `server.py` | Tool definitions and error mapping |

## Licence

MIT

TDQS

A3.9/5.0

Scored across 22 tools

Disambiguation4/5

Most tools have clearly distinct purposes (shape editing, page rendering, document inspection, connector management), but visio_render_page and visio_export_page are close enough to require careful reading, and visio_list_shapes vs visio_search_text overlap slightly in discovery.

Naming Consistency5/5

All tools follow a consistent visio_verb_noun snake_case pattern, such as visio_list_shapes, visio_add_shape, and visio_set_shape_text. Minor compound names like visio_set_shape_data still fit the same predictable convention.

Tool Count4/5

With 22 tools, the surface is larger than a typical minimal MCP server, but the count is justified by covering document, page, shape, connector, selection, export, undo, and save operations without feeling bloated.

Completeness4/5

The tool set covers the main Visio workflow: inspecting, creating, editing, connecting, selecting, rendering, saving, and undoing. Missing operations like opening/creating documents or grouping shapes are notable but not critical for common automation tasks.

Maintenance

ActivityMaintained
ResponsivenessNo issues