Model Context Protocol server for Gatan Microscopy Suite 3.60 โ multimodal TEM/STEM/EELS/4D-STEM control via local LLMs
Project description
GMS-MCP ๐ฌ
A vendor-agnostic, privacy-preserving Model Context Protocol server for multimodal electron microscopy control via local large language models.
GMS-MCP connects Gatan Microscopy Suite (GMS) 3.60 to any MCP-compatible LLM โ running entirely on your institution's hardware, with zero cloud dependencies.
Highlights
| Capability | Details |
|---|---|
| Instrument API | Gatan DigitalMicrograph / GMS 3.60 |
| LLM backend | Local Ollama (air-gap compatible) |
| Voice control | Optional local push-to-talk + Whisper transcription |
| Data handling | On-site, local-first workflow |
| Modalities | TEM / HRTEM, STEM (HAADF/BF/ABF), 4D-STEM / NBED, EELS, diffraction |
| Built-in analysis | Virtual BF/HAADF, CoM, DPC, radial profiles, max-FFT, filtering, maximum-spot mapping |
| Automation | Stage control, beam/optics control, detector configuration, tilt series, persistent live-processing jobs |
| Validation | Pydantic v2 physical-bound checks on tool inputs |
| Simulation | Physics-plausible DMSimulator for hardware-free development |
| Testing | 67-test suite (61 hardware-independent + 6 Ollama integration) |
| Transport | stdio + Streamable HTTP + optional ZeroMQ live-job bridge |
| License | MIT |
Architecture
Ollama LLM (local, port 11434)
โ LangChain ReAct agent
MultiServerMCPClient
โ stdio subprocess OR HTTP /mcp
gms_mcp.server (FastMCP 3.x)
โ ZeroMQ TCP bridge
DM Plugin (inside GMS process)
โ DigitalMicrograph Python API
Microscope hardware (TEM / STEM column)
The DMSimulator activates automatically when DigitalMicrograph is unavailable, providing physics-plausible synthetic data for all five modalities โ enabling full development and testing without a microscope.
Quick Start
1. Install
Published release from PyPI:
# Core server only
pip install nuance-gms-mcp
# With Ollama client support
pip install "nuance-gms-mcp[ollama]"
# With local voice control (microphone + Whisper transcription)
pip install "nuance-gms-mcp[ollama,voice]"
# With ZeroMQ bridge for live GMS connection
pip install "nuance-gms-mcp[ollama,zmq]"
# Install the latest code from this repository instead of the published PyPI release
pip install "git+https://github.com/NUANCE-IT/Gatan_MCP.git"
# Full development install from a local clone
git clone https://github.com/NUANCE-IT/Gatan_MCP
cd Gatan_MCP
pip install -e ".[all]"
Use pip install nuance-gms-mcp when you want the published release from PyPI.
Use pip install -e ".[all]", pip install ., or the direct GitHub URL when you
want this repository's current source tree.
2. Install Ollama + pull a model
# Install Ollama: https://ollama.ai
curl -fsSL https://ollama.ai/install.sh | sh
# Pull the recommended model (best tool-calling performance)
ollama pull qwen2.5:7b
# Alternatives
ollama pull qwen2.5:14b # higher accuracy, slower
ollama pull llama3.1:8b # reliable, widely tested
3. Run in simulation mode (no microscope needed)
# Start the interactive microscope agent
GMS_SIMULATE=1 python -m gms_mcp.client
# Or a single non-interactive query
GMS_SIMULATE=1 python -m gms_mcp.client \
--query "Acquire a 512ร512 HAADF STEM image at 10 ยตs dwell time" \
--no-interactive --verbose
3b. Run with local voice control
# Push-to-talk microphone input with local faster-whisper transcription
GMS_SIMULATE=1 python -m gms_mcp.client --voice
# Voice input plus spoken replies on macOS (uses the built-in 'say' command)
GMS_SIMULATE=1 python -m gms_mcp.client --voice --speak
# One-shot voice command, then exit
GMS_SIMULATE=1 python -m gms_mcp.client --voice --no-interactive
Voice mode records locally, transcribes locally with Whisper, and sends the resulting text transcript through the same Ollama โ MCP tool-calling path as typed instructions.
4. Connect to a live GMS instance
On the microscope PC (inside GMS Python environment):
# Install ZeroMQ inside GMS virtual environment
cd C:\ProgramData\Miniconda3\envs\GMS_VENV_PYTHON
pip install pyzmq fastmcp
# Run the DM plugin inside GMS Python console
exec(open("src/gms_mcp/dm_plugin.py").read())
On any workstation (or the same PC):
# Start the HTTP server (for remote access / Claude.ai connector)
python -m gms_mcp.server --transport http --port 8000
# Or stdio for direct Ollama use
GMS_MCP_ZMQ=tcp://microscope-pc:5555 python -m gms_mcp.client
When GMS_MCP_ZMQ is set, persistent live-processing jobs are created and managed inside
the DM bridge so long-running state stays aligned with the live GMS process.
Available Tools
| Tool | Domain | Description |
|---|---|---|
gms_get_microscope_state |
Diagnostics | Read all instrument parameters |
gms_get_front_image |
Workspace | Inspect the current front-most DM image and tags |
gms_acquire_tem_image |
Acquisition | TEM / HRTEM image with exposure, binning, ROI |
gms_acquire_stem |
Acquisition | HAADF / BF / ABF STEM scan |
gms_acquire_4d_stem |
Acquisition | Full 4D-STEM / NBED dataset |
gms_acquire_eels |
Acquisition | EELS spectrum with GIF/IFC control |
gms_acquire_diffraction |
Acquisition | Electron diffraction + auto d-spacing extraction |
gms_apply_image_filter |
Analysis | Median / Gaussian filtering on the front image or ROI |
gms_compute_radial_profile |
Analysis | 1D radial profile from diffraction or HRTEM FFT |
gms_compute_max_fft |
Analysis | Max-FFT map over local windows in the front image |
gms_start_live_processing_job |
Workflow | Start a persistent live radial-profile, difference, FFT-map, filtered-view, or maximum-spot-mapping job |
gms_get_live_processing_job_status |
Workflow | Poll a live job for iterations, status, and latest summary |
gms_get_live_processing_job_result |
Workflow | Retrieve the latest derived result from a live job |
gms_stop_live_processing_job |
Workflow | Stop a live-processing job |
gms_get_stage_position |
Stage | Read X, Y, Z, ฮฑ, ฮฒ |
gms_set_stage_position |
Stage | Move stage (validated bounds) |
gms_set_beam_parameters |
Optics | Spot size, focus, beam shift/tilt, stigmators |
gms_configure_detectors |
Detectors | Insert/retract camera, CCD temp, HAADF/BF/ABF |
gms_acquire_tilt_series |
Workflow | Automated tomographic tilt series |
gms_run_4dstem_analysis |
Analysis | Virtual BF/HAADF, CoM, DPC maps |
gms_run_4dstem_maximum_spot_mapping |
Analysis | Color maximum-spot map from a 4D-STEM dataset |
All tools enforce physical parameter bounds via Pydantic v2 before any hardware command is issued.
Example Session
You: What is the current microscope configuration?
Agent: [calls gms_get_microscope_state]
The microscope is in TEM mode at 200 kV, spot size 3,
magnification 50,000ร. Stage at X=0, Y=0, ฮฑ=0ยฐ.
Camera (OneView) is inserted at -25ยฐC.
You: Acquire a HAADF STEM image at 512ร512, 10 ยตs dwell time.
Agent: [calls gms_acquire_stem with width=512, height=512, dwell_us=10.0, signals=[0]]
Acquired 512ร512 HAADF image. Mean intensity: 487 counts,
max: 2341 counts. Total frame time: 2.62 s.
Pixel calibration: 0.0196 nm/pixel.
You: Now acquire an EELS spectrum at the Ti L-edge (460 eV).
Agent: [calls gms_acquire_eels with energy_offset_eV=400.0, dispersion_idx=1]
EELS spectrum acquired. Energy range: 400โ912 eV at 0.25 eV/channel.
Ti Lโ,โ edge detected at 462 eV. ZLP not visible (energy offset applied).
Recommend checking for beam damage โ reduce exposure if signal is sufficient.
You: Tilt to -60ยฐ and run a tilt series to +60ยฐ in 2ยฐ steps.
Agent: [calls gms_set_stage_position with alpha_deg=-60.0]
[calls gms_acquire_tilt_series with start_deg=-60, end_deg=60, step_deg=2.0]
Tilt series complete: 61 frames, ฮฑ = -60ยฐ to +60ยฐ, 1 s exposure each.
Mean intensity stable across tilt range (CV = 4.2%).
Connecting to Claude.ai
- Start the HTTP server:
python -m gms_mcp.server --transport http --port 8000 - Expose via HTTPS (e.g.
ngrok http 8000) - In Claude.ai โ Settings โ Connectors โ Add custom connector
- Enter URL:
https://your-ngrok-url.ngrok.io/mcp
Running Tests
# All hardware-independent tests (~18 s)
pytest tests/ -v -m "not ollama"
# Full suite including Ollama end-to-end tests
OLLAMA_MODEL=qwen2.5:7b pytest tests/ -v
# With coverage
pytest tests/ -m "not ollama" --cov=gms_mcp --cov-report=html
Test suite summary:
| Class | Tests | Hardware required |
|---|---|---|
TestDMSimulator |
17 | None |
TestMCPServerTools |
39 | None |
TestServerTransport |
4 | None |
TestOllamaIntegration |
6 | Ollama + model |
Project Structure
Gatan_MCP/
โโโ .github/workflows/ci.yml # lint + typecheck + test matrix + build
โโโ .gitignore
โโโ CHANGELOG.md
โโโ CONTRIBUTING.md
โโโ LICENSE # MIT, Roberto dos Reis & Vinayak P. Dravid
โโโ README.md # badges, highlights, quick-start
โโโ pyproject.toml # packaging, ruff, mypy, pytest config
โโโ src/gms_mcp/
โ โโโ __init__.py # version
โ โโโ server.py # FastMCP server โ 21 tools
โ โโโ simulator.py # DMSimulator physics twin
โ โโโ client.py # Ollama ReAct agent
โ โโโ dm_plugin.py # ZeroMQ bridge with persistent live-job backend
โโโ tests/
โ โโโ __init__.py
โ โโโ conftest.py # session fixtures, GMS_SIMULATE=1
โ โโโ test_gms_mcp.py # 67 tests (61 hardware-free)
โโโ examples/
โ โโโ 01_basic_query.py
โ โโโ 02_tem_acquisition.py
โ โโโ 03_eels_workflow.py
โ โโโ 04_4dstem_analysis.py
โ โโโ 05_tilt_series.py
โ โโโ 06_diffraction_dspacing.py
โ โโโ 07_voice_acquisition.py
โ โโโ 08_voice_confirmed_stage_moves.py
โโโ docs/
โ โโโ index.md
โ โโโ installation.md
โ โโโ architecture.md # ASCII diagram, data-flow walkthrough
โ โโโ tools_reference.md # full API for all 21 tools
โ โโโ dm_api_reference.md # DM Python quick reference
โ โโโ gms_live_setup.md # microscope PC wiring guide
Supported Ollama Models
| Model | Tool-calling | Multi-step | Latency (RTX 4090) |
|---|---|---|---|
| qwen2.5:7b โญ | 97% | 90% | 4.2 s |
| qwen2.5:14b | 99% | 95% | 8.7 s |
| llama3.1:8b | 94% | 82% | 5.1 s |
| llama3.2:3b | 82% | 58% | 2.8 s |
| mistral-nemo | 88% | 70% | 6.3 s |
Citation
If you use GMS-MCP in your research, please cite:
@article{dosReis2025gmsmcp,
author = {dos Reis, Roberto and Dravid, Vinayak P.},
title = {{GMS-MCP}: A Vendor-Agnostic, Privacy-Preserving Model
Context Protocol Server for Multimodal Electron Microscopy
Control via Local Large Language Models},
journal = {arXiv preprint arXiv:2025.XXXXX},
year = {2025},
url = {https://arxiv.org/abs/2025.XXXXX}
}
Acknowledgements
This work was supported by the NUANCE Center at Northwestern University (NSF MRSEC DMR-2308691, NSF NNCI).
We thank the developers of FastMCP, LangChain, Ollama, and the dmscripting.com community.
Contributing
See CONTRIBUTING.md. We welcome:
- New acquisition modalities (e.g., EFTEM, Lorentz TEM)
- Additional Ollama model benchmarks
- Live GMS testing reports
- Documentation improvements
License
MIT ยฉ 2025 Roberto dos Reis & Vinayak P. Dravid, Northwestern University
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nuance_gms_mcp-0.1.1.tar.gz.
File metadata
- Download URL: nuance_gms_mcp-0.1.1.tar.gz
- Upload date:
- Size: 64.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e3769f2d8d63fb8cb172ef425404394a4152dafc380ab4e8db444a790f41dd0
|
|
| MD5 |
68f1e719eb576c43250bd4971d3bc2ab
|
|
| BLAKE2b-256 |
626456153904d93db7b286a91ceb4581a4db06f44a5946fefccb2d8627e0ff60
|
Provenance
The following attestation bundles were made for nuance_gms_mcp-0.1.1.tar.gz:
Publisher:
ci.yml on NUANCE-IT/Gatan_MCP
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nuance_gms_mcp-0.1.1.tar.gz -
Subject digest:
0e3769f2d8d63fb8cb172ef425404394a4152dafc380ab4e8db444a790f41dd0 - Sigstore transparency entry: 1184755953
- Sigstore integration time:
-
Permalink:
NUANCE-IT/Gatan_MCP@725cffae0954dbf5bd00849b81bc29d544870f68 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/NUANCE-IT
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@725cffae0954dbf5bd00849b81bc29d544870f68 -
Trigger Event:
release
-
Statement type:
File details
Details for the file nuance_gms_mcp-0.1.1-py3-none-any.whl.
File metadata
- Download URL: nuance_gms_mcp-0.1.1-py3-none-any.whl
- Upload date:
- Size: 52.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab46869b2205bfc0000b3e023860918b321ddfc9df47feadecc688dee3e52559
|
|
| MD5 |
899cbbac236faf9916987fc8d0e7b09f
|
|
| BLAKE2b-256 |
0f7e2ca33261f97501275929a6174ec6be0af89ca54e284d88499d4849674f77
|
Provenance
The following attestation bundles were made for nuance_gms_mcp-0.1.1-py3-none-any.whl:
Publisher:
ci.yml on NUANCE-IT/Gatan_MCP
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nuance_gms_mcp-0.1.1-py3-none-any.whl -
Subject digest:
ab46869b2205bfc0000b3e023860918b321ddfc9df47feadecc688dee3e52559 - Sigstore transparency entry: 1184755963
- Sigstore integration time:
-
Permalink:
NUANCE-IT/Gatan_MCP@725cffae0954dbf5bd00849b81bc29d544870f68 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/NUANCE-IT
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@725cffae0954dbf5bd00849b81bc29d544870f68 -
Trigger Event:
release
-
Statement type: