Content
<!-- mcp-name: io.github.wjgoarxiv/ovito-mcp -->
<p align="center"><img src="./cover.png" width="100%" /></p>
<h1 align="center">ovito-mcp</h1>
<p align="center">
<em>The molecular-dynamics analysis swiss-army-knife for LLMs — headless, in-process OVITO for GROMACS/LAMMPS trajectories, with a clathrate-hydrate cage suite nobody else has.</em>
</p>
<p align="center">
<a href="#quick-start">Quick Start</a> · <a href="#why-ovito-mcp">Why</a> · <a href="#features">Features</a> · <a href="#tool-catalog">Tools</a> · <a href="#cage-science">Cage Science</a> · <a href="./README-Ko-KR.md">한국어</a>
</p>
<p align="center">
<img src="https://img.shields.io/badge/license-MIT-blue" />
<img src="https://img.shields.io/badge/python-3.11+-green" />
<img src="https://img.shields.io/badge/OVITO-3.15+-orange" />
<img src="https://img.shields.io/badge/MCP-FastMCP-blueviolet" />
<img src="https://img.shields.io/badge/hydrate-F3%2FF4%20%7C%20cages%20%7C%20occupancy-teal" />
</p>
---
> [!NOTE]
> **ovito-mcp** turns OVITO into a tool your LLM can drive. Point it at a GROMACS `.gro`/`.xtc` or a
> LAMMPS dump and ask — in plain language — for an RDF, a structure-type breakdown, a rendered
> snapshot, or a full clathrate-hydrate cage analysis. It runs OVITO's Python module **headless and
> in-process** (no GUI, no socket), so it works on your laptop, on a cluster, and in CI.
## See it work
<p align="center"><img src="./assets/demo.gif" width="70%" alt="ovito-mcp identifying sII hydrate cages from a natural-language prompt" /></p>
<p align="center"><em>A real run: a natural-language prompt → MCP tool calls → OVITO identifies the sII cages
(<b>128 × 5¹²</b> + <b>64 × 5¹²6⁴</b>, F4 = 0.965) and ray-traces the frame headless — every number and
render above comes straight from the engine (<a href="./demo/">how it's made</a>).</em></p>
## Why ovito-mcp?
Every other molecular-viz MCP shells out to a **running GUI over a localhost socket** — fragile,
single-session, and impossible on a headless node. ovito-mcp imports OVITO **in-process** and adds
an analysis layer no visualization server has:
| | Socket-to-GUI viz MCPs | **ovito-mcp** |
|---|---|---|
| Execution | TCP bridge to a live GUI | **headless in-process** — cluster/CI-ready |
| Install | heavy GUI app | **`pip install ovito`** |
| Analysis | render + select | **68 native modifiers** + trajectory pipeline |
| MD trajectories | load a frame | **native per-frame + time-series** |
| Clathrate hydrates | — | **F3/F4, H-bonds, cages (5¹²/5¹²6²/5¹²6⁴), GRADE, occupancy** |
**Why an MCP instead of writing an OVITO script?** Because this:
```
"Load hydrate.gro, tell me the structure type, and render it colored by coordination."
```
replaces a 30-line pipeline script, memorizing the modifier API, and a round-trip to a plot window —
and the model can chain, adapt, and show you the rendered image inline.
## Features
- **Headless in-process OVITO** — `import ovito`, no GUI, no socket; runs anywhere Python runs.
- **GROMACS & LAMMPS native** — `.gro`, `.xtc`/`.trr` (LoadTrajectory), LAMMPS dump/data, XYZ, CIF, NetCDF.
- **68 analysis modifiers** — RDF, coordination, CNA/PTM/IdentifyDiamond (ice Ih/Ic), clusters, expression selection.
- **Photorealistic rendering** — **OSPRay** ray-tracing (ambient occlusion, denoising) with an
**orthographic** default, on a dark scene; returned inline as PNGs, no display needed (Tachyon/OpenGL
also selectable).
- **Cage visualization** — `render_cages` draws each identified cage as a **colour-coded wireframe
polyhedron**: its member-O vertices *and* the H-bond edges between them share one cage-type colour
(5¹² cyan, 5¹²6⁴ red, …), width-matched, inside a yellow box — echoing the ClavisCage viewer aesthetic.
- **Clathrate-hydrate suite** — F3/F4 order parameters, hydrogen-bond networks, cage identification &
structure classification (sI/sII/sH), and cage occupancy — reused from the validated ClavisCage engine.
- **Context-safe** — every tool returns summaries, tables, counts, or images, **never raw atom arrays**.
- **stdio-safe** — a permanent fd-1 guard keeps OVITO's C++ chatter off the JSON-RPC channel.
## Quick Start
> [!IMPORTANT]
> ovito-mcp needs the `ovito` Python module (`pip install ovito`, 3.15+). It runs fully headless.
```bash
# Clone + install
git clone https://github.com/wjgoarxiv/ovito-mcp.git
cd ovito-mcp
uv venv && uv pip install -e ".[dev]" # add ,md for LAMMPS/NetCDF via MDAnalysis
uv run pytest -q # reused hydrate parity tests
# Register with Claude Desktop (claude_desktop_config.json)
```
```json
{
"mcpServers": {
"ovito": {
"command": "uvx",
"args": ["ovito-mcp"],
"env": { "OVITO_DATA_ROOT": "/path/to/your/data" }
}
}
}
```
Then just ask:
```
Open /data/sII_hydrate.gro. What hydrate structure is it, and how many of each cage type?
Render it colored by coordination number.
```
## Tool Catalog
| Group | Tool | Purpose |
|---|---|---|
| **Session/IO** | `create_session` · `get_trajectory_info` · `load_trajectory` · `export_data` · `list_sessions` · `close_session` | open files, attach trajectories, inspect, export |
| **Analysis** | `compute_rdf` · `coordination_analysis` · `structure_identification` · `cluster_analysis` · `select_expression` | native OVITO modifiers, summarized |
| **Rendering** | `render_snapshot` · `render_cages` · `render_animation` | OSPRay/Ortho PNGs (inline); cage-overlay coloured by type; movies |
| **Hydrate** | `order_parameters` · `hbond_network` · `identify_cages` · `classify_structure` · `cage_occupancy` | the clathrate-hydrate suite |
## Cage Science
> [!TIP]
> Validated against the ClavisCage reference engine: on the sII test crystal (222_S2, 1088 waters),
> ovito-mcp reports **128 × 5¹² + 64 × 5¹²6⁴ → sII** and **F4 = 0.9649**, matching the reference.
- **F3 / F4 order parameters** — F4 ≈ 0.7–0.95 = hydrate, ≈ 0 = liquid, ≈ −0.4 = ice Ih; F3 ≤ 0.04 = hydrate-like.
- **Hydrogen-bond network** — geometric O–H···O criterion (rcut 0.36 nm, angle 35°); a good framework is ~4-coordinated.
- **Cage identification** — TRACE-style ring→cage assembly with SEC/Euler validation → 5¹², 5¹²6², 5¹²6⁴, …
- **Structure classification** — GRADE-style: sI / sII / sH / mixed from cage composition.
- **Cage occupancy** — assign CO₂/CH₄ guests to cages; report filled/empty per type.
## How it works
```
ovito-mcp architecture
~~~~~~~~~~~~~~~~~~~~~~~
LLM ── JSON-RPC (stdio) ──► FastMCP server
│
┌─────────────┴──────────────┐
│ OVITOEngine (1 worker) │ ← thread-safe marshalling
│ import ovito (headless) │
└─────────────┬──────────────┘
┌───────────┬─────────┴────────┬───────────────┐
native modifiers │ extraction │ reused analysis/ (nm)
(RDF/CNA/PTM/…) │ seam (Å→nm) │ F3/F4 · H-bonds · cages · occupancy
│ │
Tachyon render ──► inline PNG
```
## Requirements
| Dependency | Required | Purpose |
|---|---|---|
| Python 3.11+ | Yes | runtime |
| `ovito` 3.15+ | Yes | headless analysis + render engine |
| `fastmcp` 3.4+ | Yes | MCP server framework |
| `numpy`, `scipy` | Yes | hydrate analysis layer |
| `MDAnalysis` | No (`[md]`) | extra trajectory/format bridge (LAMMPS/NetCDF) |
## Contributing
Issues and PRs welcome. The hydrate `analysis/` layer is shared with the sibling
[pymol-mcp](https://github.com/wjgoarxiv) — keep the two in sync.
## License
[MIT](./LICENSE).