MCPymol
MCPymol is an MCP server that lets an LLM drive PyMOL — loading structures, analyzing them, and rendering images — via natural language.
Fetch/load structures:
fetch_structure(PDB or AlphaFold via UniProt),fetch_alphafold, andload_structurefor local files, with automatic biological-assembly/multimer prep; alsofab(build peptide) andfragment.Introspect structures:
structure_info(metadata, chains, ligands),get_sequence(FASTA with numbering offsets/breaks),count_atoms.Analyze interactions:
contact_report(residue contacts classified as H-bonds, salt bridges, hydrophobic, π-stacking) andinterface_report(buried surface area, hot spots).High-level visualization:
superposition_view(colored by per-residue shift),conservation_view(evolutionary conservation via MMseqs2),print_ribbon_view.Measure:
distance,angle,dihedral,sasa,rms_cur.Align/superpose:
align,super,intra_fit,intra_rms.Manipulate atoms/objects:
select,create,extract,delete,remove,alter,alter_state,h_add,bond,unbond,rebuild,spheroid.Style & color:
show,hide,as,color,spectrum,cartoon,label,set, plus manyutil_*coloring helpers.Camera/scenes/movies:
center,orient,zoom,turn,move,clip,reset,scene,mset,mplay,frame,rock, etc.Render & export:
render(returns image inline),turntable(360° PNG sequence),ray,draw,png,mpng,save, andprint_export(watertight multi-color STL for 3D printing).Files & system:
cd,pwd,ls,system,save;execute_pymol_commandandhelpfor raw PyMOL access.Symmetry:
symexp,set_symmetry, plusisomesh/isosurfaceandsculpt_*for density/mesh work.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCPymol Fetch 1ubq and show as cartoon"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCPymol — talk to PyMOL

MCPymol is a Model Context Protocol server that lets you drive PyMOL with natural language. Load structures, set up analytical views, measure things, and explore proteins by talking to Claude or Gemini. The image above was made by typing "show me a nucleosome" into Claude Code. That was the whole prompt.
PyMOL is great, but its syntax is famously obscure — and despite the name, it isn't quite Python. MCPymol is for people who'd rather just look at structures.
What you get
A vocabulary the LLM understands. Tools like
fetch_structure,ligand_view,interface_view,mutation_view,conservation_viewdo high-level setup in one call: pick the biological assembly, hide solvent, color sensibly, label the right residues, draw the right H-bonds.Renders the model can see.
renderray-traces and hands the image straight back, so the assistant can look at what it made and fix it — rather than writing a PNG it has no way to inspect.87 PyMOL primitives exposed as individual tools (
show,hide,color,select,distance,align,spectrum, …) so the model can compose finer motions when the high-level tools don't quite fit. 135 tools in total, every parameter documented in the tool schema. When even that runs out,execute_pymol_commandpasses a raw PyMOL command straight through and waits for it, returning what PyMOL printed and, if PyMOL rejected a line, which one and why.Predicted structures. A UniProt accession fetches from AlphaFold DB and colors by pLDDT confidence in the official palette — via
fetch_structureorfetch_alphafolddirectly.Scene introspection.
list_objects,list_chains,list_ligandsandstructure_infolet the model check what's actually loaded before guessing,count_atomscatches a selection that matches nothing — otherwise invisible until the render comes out blank — andatom_propertiesreaches occupancy and altlocs that no per-residue view can show.Your own files too.
load_structureopens a local PDB/mmCIF — a model you built, a docking pose, an MD frame — through the same prep and styling as a fetched entry.Smart structure prep. Fetching a PDB code grabs the biological assembly when one exists, then runs a BFS heuristic over chain–chain contacts (
multimer_cutoff, default 8 Å) so sprawling functional multimers like the CRP pentamer or ferritin cage stay whole while crystallographic copies get dropped. Waters and crystallization additives are hidden automatically.Two-process bridge. PyMOL's GUI has its own Python; MCPymol works by running a tiny TCP listener inside PyMOL plus a separate FastMCP server outside it.
Related MCP server: PubMed MCP Server
How it talks
┌──────────────┐ MCP / stdio ┌────────────────┐ JSON over TCP ┌──────────────┐
│ Claude / │ ───────────────▶ │ mcpymol server │ ◀────:9876────▶ │ PyMOL GUI │
│ Gemini CLI │ │ (FastMCP) │ │ (plugin.py) │
└──────────────┘ └────────────────┘ └──────────────┘The plugin half runs inside PyMOL and dispatches to pymol.cmd. The bridge half is what the MCP client launches. They talk over a local TCP socket because PyMOL's GUI ships its own Python interpreter, which cannot import the packages the MCP server needs — so the two halves cannot live in one process.
Both halves must run on the same machine: several tools hand files between them through the filesystem.
Try it
"Fetch ubiquitin (1ubq) and show it as a cartoon, then show me the render." "Color the alpha helices red and the beta sheets blue." "What ligands are in 1HSG?" "Show the binding pocket around MK1 in 1HSG." "Highlight mutations E6V, K16E, and V67F in hemoglobin (4HHB)." "Run a Poisson-Boltzmann electrostatics calculation on 1LYZ." "Get the AlphaFold model for P69905 and tell me how confident it is." "Superpose 1AKE onto 4AKE and show me where adenylate kinase moves." "Make me a turntable animation of the nucleosome."
Tip: if the model isn't sure what's loaded, ask it to list the objects — it'll call list_objects and ground itself before guessing names.
What can I ask?
Organised by the question, not the tool.
Question | Tool |
What is this structure — resolution, method, organism? |
|
What's the sequence, and how does it map to the residue numbering? |
|
What's loaded / what chains / what ligands? |
|
Can I open my own file rather than a PDB code? |
|
What are this atom's occupancy / altloc / B-factor? |
|
What holds this ligand in its pocket, and how tightly? |
|
How big is this interface, and which residues matter? |
|
Where do these two structures differ? |
|
How far apart / what angle / how much surface? |
|
Which parts are conserved? Flexible? Confident? |
|
Is this atom really there, or is it half-occupied? |
|
How much do the members of this ensemble disagree? |
|
How good is this cryo-EM model, per residue? |
|
What's the voxel size / geometry of this map? |
|
Can I see the density around this ligand? |
|
Which parts of this map are actually well resolved? |
|
What does it look like? |
|
Can I keep this scene? |
|
Can I print it? |
|
The pattern that works best: report first, then draw. contact_report tells
you Asp30 makes a salt bridge at 2.7 Å; ligand_view then shows you where it
sits. Asking only for the picture gets you a picture you have to interpret
yourself.
Requirements
PyMOL — developed against Open-Source PyMOL 3.1 (
brew install pymolon macOS; on Linux,conda install -c conda-forge pymol-open-sourceorapt-get install pymolon Ubuntu 26.04+). Debian/Ubuntu 22.04 and 24.04 ship PyMOL 2.5 viaapt, which works across the standard tools and views (onlyprint_ribbon_view(..., spine_in_strands=False)requires PyMOL 3.1). The Schrödinger Incentive build works if its embedded Python is 3.10 or newer (print(sys.version)inside PyMOL); older Incentive 2.x builds are not supported. MCPymol drives an existing PyMOL installation and does not bundle one.Python 3.11+ for the bridge (separate from PyMOL's internal Python). On Ubuntu 22.04 where system
python3is 3.10,uv tool install --python 3.12 mcpymolfetches a compatible Python automatically.An MCP client — Claude Code, Claude Desktop, or Gemini CLI.
Optional, per feature:
For | You also need |
|
|
| the |
| network access to an MMseqs2 server (ColabFold's public API by default). The chain's sequence is sent to that server, so for an unpublished sequence point |
| network access to the RCSB |
Installation
There are two halves to wire up: the native plugin (runs inside PyMOL) and the MCP bridge (runs outside, and is what your AI assistant launches). Both come from the same package.
1. Install MCPymol
uv tool install mcpymolpipx install mcpymol works the same way. There is no need to clone the
repository unless you intend to work on MCPymol itself.
Check it landed somewhere your shell can see:
which mcpymol # if this prints nothing, run: uv tool update-shellNote the full path it prints — you will want it in step 3. uv and pipx
install into ~/.local/bin, which is not on everyone's PATH, and an MCP client
started by the OS rather than from your shell does not inherit your PATH at
all. Wiring the assistant to a bare mcpymol when it is not on PATH fails at
launch with spawn mcpymol ENOENT, not at install time.
Why not
uvx mcpymol?uvxruns the bridge perfectly well, but it is the wrong tool for step 2: it unpacks the package into~/.cache/uv, and the plugin has to be loaded by absolute path, so the line written into your PyMOL startup file would point into a cache thatuv cache cleanreclaims.uv tool installputs it somewhere permanent — and lets both halves come from one installation, so the bridge and the plugin cannot drift apart.
2. Start the native plugin
The plugin runs inside PyMOL, which has its own Python interpreter — it cannot import the installed package, so it is loaded from a file path. Let MCPymol find that path for you:
mcpymol --install-pluginThat adds a small managed block to ~/.pymolrc.py, so PyMOL loads the plugin
on every launch. Restart PyMOL and you should see:
MCPymol Native Plugin listening on 127.0.0.1:9876Re-run it after upgrading MCPymol — the block embeds a path into one
installation and is rewritten, not duplicated. mcpymol --uninstall-plugin
removes it and leaves the rest of your .pymolrc.py alone.
If you would rather wire it up yourself, mcpymol --plugin-path prints the
path, and you can run it from the PyMOL command line or add your own line to
~/.pymolrc.py.
Changing the port. Set MCPYMOL_PORT before launching both PyMOL and
the bridge — see Configuration.
3. Register the bridge with your AI assistant
Pick one. Use the full path from which mcpymol — it is the same
installation the plugin came from, and a bare mcpymol only works if that
directory is on the PATH of whatever launches the client.
Claude Code CLI
claude mcp add mcpymol -- "$(which mcpymol)"Start a new Claude Code session.
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"mcpymol": {
"command": "/absolute/path/to/mcpymol"
}
}
}The absolute path is not optional here: Claude Desktop is launched by the OS rather than from your shell, so it never inherits your PATH. Restart Claude Desktop afterwards.
Gemini CLI
gemini mcp add mcpymol "$(which mcpymol)"
gemini mcp refreshWithout installing — uvx
To run the bridge without installing anything, point your assistant at
uvx mcpymol:
claude mcp add mcpymol -- uvx mcpymolYou still need the plugin, and step 2's command is not available to you —
nothing was installed. Run it through uvx instead:
uvx mcpymol --install-pluginThat writes a path into ~/.cache/uv (see the note in step 1), so uv cache clean or a uvx upgrade will break it and you will have to re-run it. uvx
also resolves the newest release on each launch, so the bridge can drift ahead
of the plugin. This path trades a permanent install for maintenance; if that
sounds worse than installing, install.
Restricted environments — no uv
If uv is blocked by your org's security policy, use a standard venv with Python 3.11 or newer. On Debian/Ubuntu you may need sudo apt-get install python3-venv pymol first (on Ubuntu 22.04, where default python3 is 3.10, install a newer Python such as python3.11-venv and invoke python3.11 -m venv below).
python3 -m venv ~/.venvs/mcpymol
~/.venvs/mcpymol/bin/pip install --upgrade pip
~/.venvs/mcpymol/bin/pip install mcpymol
~/.venvs/mcpymol/bin/mcpymol --install-plugin
# Point the assistant directly at the venv binary
claude mcp add mcpymol ~/.venvs/mcpymol/bin/mcpymol
# or
gemini mcp add mcpymol ~/.venvs/mcpymol/bin/mcpymolIf your network blocks PyPI, install from your internal mirror with pip install --index-url ....
Upgrading
Upgrade the way you installed — uv tool upgrade mcpymol, pipx upgrade mcpymol, or <venv>/bin/pip install --upgrade mcpymol. Then restart
PyMOL and reconnect the MCP server in your client (/mcp in Claude Code).
Both halves have to move together, and neither moves on its own. The plugin is loaded into PyMOL's memory at startup, and the bridge is a process your MCP client launched — upgrading the package on disk changes neither until each is restarted. PyMOL will happily keep running the plugin it loaded days ago against a freshly upgraded bridge.
You do not normally need to re-run --install-plugin: uv tool, pipx and
a venv all upgrade the package in place, so the path in ~/.pymolrc.py still
points at the right file. Re-run it if you move the installation — switching
install method, rebuilding the venv, or using the uvx path, whose cache
directory does change.
A mismatched pair fails in a way that reads like a bug in a tool rather than a stale process: calls that should work report unknown actions, or a tool fixed in the release you just installed keeps misbehaving.
Working on MCPymol itself
For development, clone the repo and run from the checkout — this is the only path that needs a clone:
git clone https://github.com/chemrich/MCPymol.git
cd MCPymol
uv sync
uv run mcpymol --install-plugin
claude mcp add mcpymol -- uv --directory /absolute/path/to/MCPymol run mcpymolSee CONTRIBUTING.md.
Configuration
Everything is optional; the defaults are what the tools are tuned for. Set them before launching PyMOL and the bridge.
Variable | Default | What it does |
|
| Bridge ↔ plugin TCP port. Must match on both sides. |
|
| Plugin side: set to |
|
| How long the plugin waits for one complete request before answering with an error. Bounds how long a stalled client can hold the single-threaded accept loop. |
|
| Largest single request the plugin will accept. |
|
| Plugin side: how much of what PyMOL printed one |
|
| Plugin side: how long an |
|
| Plugin side, macOS GUI only: how long after its last request the plugin lets macOS App Nap PyMOL again. |
|
| Socket budget for operations that legitimately take minutes — |
|
| Above this, |
|
| Wall-clock ceiling on the external |
| ColabFold public API | MMseqs2 server for |
|
| Socket budget for the standalone |
| AlphaFold DB prediction API | Where |
| AlphaFold DB files | Legacy filename template, used only when you pin |
| RCSB data API | Base URL for the metadata |
MCPYMOL_PORT=9867 open -a PyMOL # macOS
MCPYMOL_PORT=9867 mcpymol # bridgeTroubleshooting
Symptom | Likely cause | Fix |
Every tool returns "Socket connection failed: nothing is listening on 127.0.0.1:9876 … Is the PyMOL plugin running?" | Plugin not loaded in PyMOL |
|
"Address already in use" on plugin start | A previous PyMOL session left the port open, or another app uses 9876 | Quit lingering PyMOL processes, or set |
Long | You're on a pre-2026-05 version of MCPymol that capped recv() at 8 KB | Upgrade — the bridge now drains the response in full |
| First call hits the ColabFold MMseqs2 API (30 s–few min); subsequent calls for the same sequence hit a local cache | If you have an internal MMseqs2 server, set |
|
|
|
A tool reports a file "did not appear" | PyMOL and the bridge are on different machines — they exchange files through the filesystem | Run both on the same host |
| The PNG exceeded the inline limit; base64 inflates it by a third | Ask for a smaller |
| The accession is valid but AlphaFold DB has no model at that version | Try another |
A view comes out blank | The selection matched no atoms |
|
A long operation returns "PyMOL accepted '…' but sent no reply within N s" | Something slower than its budget. The request was not cancelled, so PyMOL may still be working on it | Check what PyMOL has done before re-sending; raise |
A render took many minutes and says "the computer was asleep for N s of it", or any tool's timeout ends "asleep for N s of this wait" | The Mac slept during the call. Nothing runs while it sleeps — PyMOL, the bridge or the client — and the wait resumes on wake, which makes it look like a stall | Keep the machine awake for long unattended runs, e.g. |
Slow renders on a Mac: a ray trace that normally takes seconds takes minutes while PyMOL's window is in the background | macOS App Nap drops a background app to the lowest priority, and under load a 1 s ray trace was measured at 74–349 s | The plugin holds off App Nap while it is serving requests ( |
| PyMOL loaded an old plugin, which reports success for every command without running it first | Restart PyMOL so it loads the plugin from this install ( |
| PyMOL's main thread was held (a long command, an open dialog, a movie being rendered, a hang) for | Look at the PyMOL window; nothing from that request was run |
A tool reports an unknown action, or a bug you just upgraded past is still there | PyMOL is still running the plugin it loaded at startup, from before the upgrade | Restart PyMOL, then reconnect the server in your client ( |
New tools don't show up after an upgrade | The MCP client is still running the previous bridge process | Reconnect the server in your client, or start a new session |
A fetch reports success but nothing is loaded | Pre-v1.4.0 behaviour: | Upgrade — fetches now verify atoms arrived and say so plainly, and no longer clear the session on failure |
| The camera is pointed at nothing, or the session is wedged after heavy use |
|
Tests
uv run pytestThe tests that run by default mock the socket layer and PyMOL's cmd module, so they need neither PyMOL nor a network, and cover the socket payloads, the bridge framing, the conservation pipeline (A3M parsing, Shannon entropy, MMseqs2 mocking, MSA→B-factor mapping), the mesh-repair paths, and every view. tests/test_bridge_roundtrip.py additionally runs the real bridge against the real plugin listener over TCP on an ephemeral port, so the wire format is checked against itself rather than against a mock.
The two opt-in suites
The rest are deselected by default, because they need things CI does not have. Both are worth running before a release tag:
uv run pytest -m live # needs a test PyMOL on its own port: see CONTRIBUTING.md
uv run pytest -m network # hits real external APIs
-m liveclears the PyMOL session it connects to. So it runs only against a port you name for testing; your everyday PyMOL's port, 9876 or anMCPYMOL_PORTin your shell, is never assumed to be disposable.
-m live exists because a mocked suite asserts the payload we send, which can never tell you whether PyMOL will accept it — and that gap is where every wiring bug has lived: tools calling cmd functions that don't exist, arguments bound in the wrong order, renders that come back blank. It calls every registered tool once and asserts only that each is wired (the action resolves, the arguments bind), not that it succeeds, since many tools error honestly without the right context. New tools are swept automatically. Asking for it and having no live test pass is a failure, not a green run of skips, and it detects a wedged session rather than reporting a hundred confusing failures.
Treat a green default run as necessary, not sufficient.
Layout
Module | Responsibility |
| the shared FastMCP application |
| socket protocol to the in-PyMOL plugin |
| fetching/loading structures, sessions, introspection |
| one thin tool per |
| the |
| scene conventions shared across the presets |
|
|
|
|
| MSA + Shannon entropy |
|
|
| cryo-EM occupancy, ensembles, maps and local resolution |
| parsing the PDB records PyMOL hands back as text |
| watertight STL export |
|
|
| the half that runs inside PyMOL |
mcpymol/cli.py is the entry point (the mcpymol command). mcpymol/server.py imports every tool module and re-exports everything, so from mcpymol.server import ligand_view still works.
The view library
These are the high-level visualization tools. Each does its own setup — coloring, transparency, H-bonds, labels — in one prompt.
ligand_view — binding site
Pocket residues (within 5 Å of the ligand) as element-colored sticks with CA labels, ligand as yellow sticks, H-bonds as yellow dashes, protein as a translucent cartoon.
Show me the ATP binding site in 1ATP

interface_view — protein–protein interface
Chain A marine, chain B salmon. Interface residues (within 4 Å of the partner) as solid surface patches with sidechain sticks and CA labels. Cross-chain H-bonds as yellow dashes.
Show the interface between chain A and chain D in 1BRS

putty_view — B-factor flexibility
Tube radius and color scale with B-factor: blue/thin = rigid, red/thick = flexible. A 70%-transparent surface adds shape context.
Show the B-factor flexibility of 1UBQ as a putty view

bfactor_view — B-factor flexibility, plain cartoon
The same color story as putty_view (blue → red on B-factor) but on a plain cartoon. Cheaper, cleaner in figures where you don't want the putty distortion.
Color 1UBQ by B-factor
hydrophobic_surface_view — surface chemistry
Surface colored by amino-acid chemistry: orange = hydrophobic, white = polar, sky blue = positive, salmon = negative. Useful for spotting hydrophobic patches, membrane belts, and charge complementarity.
Show the hydrophobic surface of 1TCA

electrostatic_view — approximate electrostatics
Red→white→blue surface coloring driven by per-residue pKa-weighted partial charges. Two modes: atomic (charges on the actual charge-center atoms — localized, natural falloff) and residue (uniform across charged residues — saturated patches).
Show the electrostatic surface of 1LYZ

poisson_boltzmann_view — true PB electrostatics
Full Poisson-Boltzmann potential via APBS and PDB2PQR, mapped onto the surface at ±20 kT/e. Physically correct, accounts for solvent screening and ionic strength.
Prerequisites (must be on
PATH):brew install brewsci/bio/apbs pip install pdb2pqr
Run a Poisson-Boltzmann electrostatics calculation on 1LYZ

conservation_view — evolutionary conservation
Pipeline: extract the chain's sequence → submit to MMseqs2 (ColabFold public API by default, so the sequence leaves your machine; override with MCPYMOL_MMSEQS_URL) → parse the A3M alignment → compute per-position Shannon entropy → map onto B-factor and color via cyan_white_magenta spectrum.
Magenta = conserved, white = moderate, cyan = variable. First call takes 30 s – few minutes depending on sequence length; results are cached in memory by sequence, so re-running on the same protein (or changing only the color scale) is instant.
Color lysozyme (1LYZ) by conservation

Lysozyme against 5,507 homologues. The variable surface loops go cyan while the core and the substrate-binding cleft stay magenta — conservation tracking function, which is the whole reason to compute it.
crosslink_view — disulfides & metal coordination
CYS sidechains and disulfide bonds in yellow, metal coordination bonds in orange, the rest of the protein as a thin grey cartoon.
Show the disulfide bonds in 1CEL

pocket_view — binding pocket surface
The pocket cavity (residues within 5 Å of the ligand) as a semi-transparent surface colored by chemistry. Sticks for the pocket sidechains, yellow sticks for the ligand, cyan dashes for H-bonds.
Show the binding pocket around MK1 in 1HSG

pharmacophore_view — ligand pharmacophore features
The ligand colored by pharmacophore type: violet = aromatic ring carbon, yellow = aliphatic carbon, sky blue = N (donor/acceptor), salmon = O (acceptor), gold = S, pale green = halogen. Interacting residue sticks with CA labels, cyan dashes for H-bonds.
Show the pharmacophore features of MK1 in 1HSG

mutation_view — mutation hotspots
Grey cartoon, mutated sidechains as magenta sticks with white CA labels, neighboring residues (within 4 Å) as thin element-colored sticks for packing context. Standard A123G notation; optional chain prefix A:A123G.
Highlight mutations E6V, K16E, and V67F in hemoglobin (4HHB)

textbook_view — cel-shaded illustration
White cartoon + surface with heavy ray-trace contours. The cel-shaded look kicks in after you run ray (or ask the model to render).
Make 4HHB look like a textbook illustration

cinematic_view — fog and shadows
Depth-cueing + fog + soft shadows on a black background. Best on big assemblies — ribosomes, capsids, nucleosomes — where you want a sense of scale. Run ray for the full effect.
Give me a cinematic view of GroEL

Depth cueing needs scale to pay off — this is one GroEL ring down its seven-fold axis. On a small globular protein the effect is mostly lost.
pointillist_view — starfield surface
Replaces the surface with a dense dot cloud; ligands become bright yellow stars. More art than analysis.
plddt_view — AlphaFold confidence
Colors a predicted model by pLDDT in AlphaFold's official palette: dark blue >90 (very high), light blue 70–90 (confident), yellow 50–70 (low), orange <50 (very low). Reports the breakdown, e.g. "very high: 62%, confident: 21%, …".
pLDDT is stored in the B-factor column, which is why bfactor_view and putty_view render these models backwards — they read low B as rigid, whereas low pLDDT means the model doesn't know. plddt_view warns if the B-factors don't look like pLDDT at all.
Get the AlphaFold model for P0DTC2

Mean pLDDT 67.1 across 1273 residues — 7% very high, 49% confident, 20% low, 24% very low. The orange tails are the point: AlphaFold is telling you it does not know where they go, and no amount of rendering makes that a structure.
superposition_view — where two structures differ
Superposes mobile onto target, then colors the mobile structure by how far each residue's CA actually moved: blue = unchanged, red = most shifted. The target stays as a grey reference. Reports the RMSD, the mean and max shift, and names the worst-shifted residues.
An RMSD alone tells you a structure moved; this tells you where.
Superpose 4AKE onto 1AKE and show me where it moves

Adenylate kinase, open against closed: the core fits at 2.07 Å RMSD while residues 145–152 move up to 24 Å. That is the LID domain closing over the substrate, and it is the whole reason to colour by deviation rather than quote one number.
Both structures have to be loaded at once, and fetch_structure clears the
session by default — fetch the second with replace=False. Compare single
chains when the entries are multimers: superposing one dimer onto another fits
the assembly rather than the fold, which reports 18.5 Å for this same pair.
Analysis — answers with numbers
The view presets draw interactions; these report them. Both matter, and they compose: run the report to get the numbers for your figure legend, run the view to make the figure.
contact_report — what touches what
Lists contacting residue pairs closest first, with the minimum heavy-atom distance, how many atoms are involved, and a classification: salt bridge, hydrogen bond, hydrophobic, polar contact, or π-stacking (parallel vs T-shaped from the interplanar angle).
contact_report("1hsg and resn MK1", "1hsg and polymer")Criteria are heavy-atom distances — salt bridge ≤ 4.0 Å between charged sidechain tips, H-bond ≤ 3.5 Å between N/O pairs, hydrophobic ≤ 4.5 Å between C/S, ring centroids ≤ 5.5 Å — because crystal structures usually have no hydrogens. A reported hydrogen bond is therefore a donor–acceptor pair with plausible geometry, not one verified against a hydrogen position.
Ring perception needs bond orders, which a PDB dump doesn't carry, so aromatics are detected for the standard aromatic amino acids only; ligand rings show up as hydrophobic contacts rather than being mis-called as stacking.
What holds MK1 in the HIV protease pocket?
26 residue pairs in contact within 4.0 A between '1hsg and resn MK1' and '1hsg and polymer':
B/MK1902 -- B/ASP25 2.63 A hydrogen bond, polar contact, contact (8 atom contacts)
B/MK1902 -- A/ASP25 2.77 A hydrogen bond, contact (8 atom contacts)
B/MK1902 -- B/GLY27 3.03 A hydrogen bond, polar contact, contact (8 atom contacts)
B/MK1902 -- B/ASP29 3.06 A hydrogen bond, polar contact, contact (6 atom contacts)
B/MK1902 -- A/GLY48 3.15 A hydrophobic, contact (6 atom contacts)
B/MK1902 -- B/VAL32 3.32 A hydrophobic (2 atom contacts)
... and 20 more pairs (raise max_pairs to see).
Interaction types across all pairs: 20 hydrophobic, 14 contact, 5 hydrogen bond, 4 polar contact.Both copies of the catalytic Asp25 — one from each chain of the protease dimer —
hydrogen bond the inhibitor at 2.63 and 2.77 Å. That is the interaction the drug
was designed to make, read straight off the structure. It is the same pocket the
ligand_view image above shows; the picture and the numbers are two views of one
question.
interface_report — how big is this interface
Buried surface area from ΔSASA (free minus bound), the per-side figure papers quote, a ranking of residues by how much surface each buries, and a breakdown by residue chemistry.
It also interprets the number: under ~400 Ų per side is usually crystal packing rather than a biological interface; over ~1000 Ų is a substantial, likely specific association. Guidance from PDB-wide surveys, not a verdict.
How big is the barnase–barstar interface in 1BRS?
Interface between chains A and D of 1brs:
Buried surface area: 777 A^2 per side (1,553 A^2 total).
That is a typical size for a specific but transient protein-protein interface.
Interface residues: 22 in chain A, 19 in chain D.
Composition by buried area: 41% charged, 32% polar, 28% hydrophobic.
Chain A hot spots: ARG59 (154 A^2), HIS102 (107 A^2), ARG83 (78 A^2), GLU60 (69 A^2), ...
Chain D hot spots: ASP35 (120 A^2), TYR29 (97 A^2), ASP39 (86 A^2), TRP44 (75 A^2), ...Barnase–barstar is the textbook electrostatically-driven interface, and the numbers say so unprompted: 41% of the buried area is charged, and the hot spots it ranks — Arg59/His102 on barnase, Asp35/Asp39/Trp44 on barstar — are the residues the mutagenesis literature identifies.
structure_info and get_sequence — what am I looking at
structure_info combines what PyMOL knows (chains, counts, ligands, states,
space group) with RCSB entry metadata (title, method, resolution, release date,
source organism), and flags a probable AlphaFold model when the B-factor column
looks like pLDDT.
1hsg — CRYSTAL STRUCTURE AT 1.9 ANGSTROMS RESOLUTION OF HUMAN IMMUNODEFICIENCY
VIRUS (HIV) II PROTEASE COMPLEXED WITH L-735,524, AN ORALLY BIOAVAILABLE
INHIBITOR OF THE HIV PROTEASES
X-RAY DIFFRACTION, 2.00 A resolution, released 1996-04-03
Source: Human immunodeficiency virus 1
1,686 atoms, 198 residues, 127 waters
Chains (2): A, B
Ligands in '1hsg': MK1
Space group P 21 21 2, cell 59.6 x 87.1 x 46.7 Aatom_properties reads properties that live on individual atoms rather than
residues or objects — occupancy, alternate conformations, per-atom B-factor,
formal charge. Nothing else reaches them: the PyMOL call that exposes them
returns an object that cannot cross the bridge, so the plugin flattens it on
the way out.
2 atoms in '1hsg and resi 25':
chain resi resn name b q
A 25 ASP OD1 18.42 1.00
A 25 ASP OD2 21.07 0.50That 0.50 is the tool's reason to exist: a sidechain modelled in two conformations, invisible to every per-residue view.
get_sequence returns FASTA — plus the two things the sequence alone hides and
that routinely cause mistakes: the numbering offset (PDB numbering rarely
starts at 1, so "residue 50" in a paper and position 50 in the sequence are
usually different residues) and chain breaks where loops went unmodelled.
Rendering and sessions
render — see what you made
Ray-traces the current scene and returns the image as MCP image content, so the model can actually look at it and iterate. This is the tool to use instead of ray + png, which only leave a file behind.
Defaults to 1000×750 — the image is inlined into the conversation, and base64 inflates it by a third. Above 5 MB (MCPYMOL_MAX_IMAGE_BYTES) it returns the path instead, and keeps the file there even if you did not pass a filename, so a render that took minutes is not thrown away for being too big to show.
Every render is ray-traced, and ray_trace=False does not change that: PyMOL's fast unshaded frame grab needs its GUI thread, which the plugin does not run on, so that path wrote blank images. The flag is accepted and ignored, with a note in the reply, rather than silently handing back a blank PNG. To make a render cheaper, ask for a smaller width/height. render also detects the two ways an image comes back empty — a single flat colour, or nothing written at all — and says so instead of returning a black square.
turntable — 360° animation
Writes a numbered PNG sequence spinning the camera a full turn, plus the ffmpeg command to assemble it. Defaults to 36 frames (10° apart) at 800×600.
Every frame is ray-traced, for the same reason render is — the unshaded OpenGL path silently produced blank frames over this bridge. That makes it slow: 36 frames of a large assembly can take an hour, so start with a low frames count and a small width/height before committing to a long run.
Make me a turntable animation of 1AOI
save_session / load_session — keep a scene
.pse round-trips the entire session: every object, selection, representation, color, scene and the camera. Save before experimenting with a scene that took effort to build. load_session(merge=True) adds a saved scene to the current one rather than replacing it.
🖨️ 3D Printing Export
The print_export tool turns a structure into watertight STL files ready for
multi-colour 3D printing. PyMOL's open-source build can't write STL and its OBJ
exporter dumps the whole visible scene as non-manifold surface soup —
print_export works around all of that: it isolates each colour group, exports
it, and rebuilds a watertight, manifold solid per group. Every STL is written in
PyMOL's model coordinates, so a slicer can load the groups as aligned
multi-material parts.
This tool needs the optional print extra (trimesh, pymeshlab, scipy,
scikit-image, manifold3d, numpy):
Install it into the same environment MCPymol is already in — a bare
pip install picks whatever pip is first on your PATH, which is usually a
different interpreter entirely, and leaves print_export still reporting the
dependencies missing:
uv tool install 'mcpymol[print]' # if you used uv tool
pipx install --force 'mcpymol[print]' # if you used pipx
~/.venvs/mcpymol/bin/pip install 'mcpymol[print]' # if you used a venv
uv sync --extra print # from a checkoutRe-running over an existing install is fine — it adds the extra in place.
On Linux, pymeshlab also needs the system OpenGL library, even headless.
Without it the Poisson method fails (libOpenGL.so.0: cannot open shared object file) and auto falls back to voxel, saying why. On Debian and
Ubuntu: sudo apt-get install libopengl0. macOS needs nothing extra.
Export T7 RNA polymerase (1MSW) for 3D printing with the protein and the
nucleic acid as separate coloursThis produces one STL per group (e.g. 1MSW_protein.stl,
1MSW_nucleic.stl). method="auto" (default) picks the cheapest path that
works: compact structures (e.g. a GFP barrel) often export already-watertight,
so it does a light cleanup rather than Poisson, which can degrade an
already-closed surface. Otherwise it falls back to Poisson, then voxel.
method="poisson" forces detail-preserving reconstruction (best for bulky
chains); it runs in a child process, because PoissonRecon ends the process it
runs in when it gives up. method="voxel" is robust for thin cartoons and
nucleic acids, and is the one to use for ribbons. In your slicer, load the first
STL, then add the others as parts (don't re-centre) and assign a filament per
part.
What gets exported (representation):
"surface"(default) — each group's molecular surface."cartoon"— the triangles the group's objects display: cartoon, plus any surface shown. Hidden loops and per-object cartoon types are kept. Sticks and spheres are left out, and the result names what was left out."displayed"— everything PyMOL draws for the group's objects: the triangles, plus sticks, spheres, lines, ribbon and distance dashes, merged with an exact boolean union. Dashes become one solid rod for the export only. Lines, dashes, ribbon, mesh and dots are sized in pixels unless their*_radiussetting is set, so set it (e.g.dash_radius) for a definite size in Å.
In cartoon and displayed modes a group names whole objects; name distance and
CGO objects in the group too, e.g. lig=(lig or hbonds).
Coordinates and size. STLs are in PyMOL model coordinates — the numbers
get_coords reports — whatever the camera is doing, and your view is left as it
was. Groups from one call, or from separate calls at the same scale, line up.
mm_per_angstrom (default 1.0) sets the print scale: it is applied to every
group about the origin after repair, so parts stay registered, while
voxel_pitch stays in Å. The result gives each part's size in mm, the assembled
size, and a warning when a part is small enough for a slicer to take it for
inches and enlarge it 25.4× (under 9 mm³ in PrusaSlicer, 8 in Bambu Studio and
OrcaSlicer; Bambu's 2.8.4 beta does it without asking), with the scale that
avoids it.
Separate pieces (bodies). A group can legitimately come out as several
pieces: chains whose cartoons don't touch (4hhb's two dimers), or four hemes.
bodies="all" (default) keeps every piece and the result says "prints as N
separate pieces"; bodies="largest" keeps one and warns when that drops more
than 1% of the volume. Enclosed cavities are filled and stray fragments removed
either way, and the result counts both.
Voxel growth (undo_voxel_growth, default on). Voxelising grows every
surface by about 0.62 voxel; this moves it back, never past half a thin part's
thickness. Gaps narrower than about 2.5 × voxel_pitch fuse while voxelising
and can't be reopened, so for a designed clearance use voxel_pitch ≤ gap / 2.5,
and measure clearances on the exported STLs.
Warnings in the result need action before printing: a cartoon feature
thinner than 3 voxels (naming the setting and object), rods or spheres thinner
than 0.8 mm at the chosen scale (naming what draws them, e.g. set valence, 0
for double bonds), a dropped piece, a part a slicer would read as inches, and
shown residues whose Cα lies outside the printed mesh — typically next to a
hidden residue, where loop smoothing pulls the tube away and a part meant to
attach there will not touch.
print_ribbon_view — print-ready chunky ribbons
A preset that solves the classic problem of printing cartoons: PyMOL builds
each β-strand and loop as a separate mesh segment, so the strand→loop junctions
have no connecting geometry and slice into fragile, disconnected pieces.
print_ribbon_view configures chunky β-strand arrows and a fat helix, hides
the loop cartoon, and adds a continuous backbone spine (<obj>_spine, a
cartoon tube that ignores secondary structure and runs unbroken through the
whole chain). Exported together the voxel step fuses them into one watertight
solid with no junction discontinuity — and the spine doubles as internal rebar
for print rigidity. Tune spine_radius for more or less reinforcement.
The style is set on the object and its spine only; other objects and PyMOL's
global settings are left alone. Residues that are peptide-linked but have no CA
atom, such as GFP's chromophore (CRO), used to break the spine; it is now carried
through them on the spine copy, without renaming or renumbering anything in your
object (bridge_modified, default on). The result names each residue it bridged,
or says why it could not.
print_ribbon_view(obj_name="1ema")
print_export(obj_name="1ema", groups="1ema=(1ema or 1ema_spine)",
representation="cartoon", method="voxel", voxel_pitch=0.2)
GFP's β-barrel with the chunky arrows applied. The bulges running along each strand are the spine tube passing through — the internal rebar, visible before it gets fused into one solid on export.
strand_width and strand_thickness (defaults 2.8 and 2.0) are PyMOL's
cartoon_rect_length and cartoon_rect_width; PyMOL draws a strand √2 times
both, so the defaults give strands about 4.0 × 2.8 Å and a β-barrel's wall
closes up. To see into a barrel, thin the strands and take the spine out of
their interiors:
print_ribbon_view(obj_name="2b3p", strand_width=2.0, strand_thickness=1.0,
spine_in_strands=False)Measured on GFP (2b3p): the see-through share of the barrel wall goes from 8% to
29%, the spine no longer bulges out of the thin strands (399 ų of it did; 1 ų
does now), and the model still exports as one piece. strand_overlap (default
2, at least 2) is how many residues of spine stay at each strand end, where the
loops fuse to the strands.
Cryo-EM: occupancy, ensembles and maps
Ten tools for the things a viewer usually throws away. Every one of them exists because a render that looked fine was hiding something, so they share a rule: say what is being shown, and refuse when the picture would be meaningful-looking and wrong.
occupancy_view and altloc_view — is this atom really there
occupancy_view colours and scales by per-atom occupancy q, de-emphasising
alternates at q<1 in proportion, so a half-occupied conformer looks
half-there. altloc_view shows every alternate location at once, one colour per
group, occupancies labelled — PyMOL shows one by default, which quietly turns a
statement about heterogeneity into a single structure.
"Occupancy" names two incompatible quantities: the crystallographic q above,
and the fraction of imaged particles containing a subunit. A model can be
q = 1.0 everywhere while its subunit is present in half the particles. Both
are true, they are different questions, and occupancy_view reports only the
first — the legend says which.
occupancy_view(obj_name="1ejg")
altloc_view(obj_name="1ejg")ensemble_spread_view and morph_states — how much do the states disagree
ensemble_spread_view computes per-residue RMS deviation across the states of a
multi-model object, pushes it into the B-factor column and putty-scales it, so
spread reads as tube width as well as colour. Spread is a description of how
much the deposited members differ — not a calibrated uncertainty and not an
error bar.
morph_states interpolates between states, and the value in it is the refusal.
A morph is only meaningful when every state shares a topology; across
independently reconstructed volumes it animates a correspondence nobody
established, so the tool checks and declines. (cmd.morph is Incentive-only —
on open-source PyMOL the check still runs and reports, and only the
interpolation is unavailable.)
restore_bfactors puts back what these views overwrote.
ensemble_spread_view(obj_name="1l2y")
morph_states(obj_name="1l2y", validate_only=True)qscore_view — per-residue model quality, already published
Colours a model by Q-score parsed straight out of its wwPDB validation report. No network, no map, no computation — the numbers exist, nothing surfaces them. Two things to expect from real data: entries deposited before the September 2023 rollout carry no Q-scores at all, and real Q-scores go negative, so the published 0–1 framing is the intended range rather than the observed one.
qscore_view(obj_name="9c0k", validation_path="9c0k_validation.xml.gz")map_info — the number nothing displays
Reads an MRC/CCP4 header and reports the geometry, above all voxel size. Only the 1024-byte header is read: the data is never loaded, PyMOL is never touched, nothing goes over the network.
Voxel size is not stored, it is derived, and the derivation has a trap — it is
cella/m (the grid sampling), not cella/n (the stored extent). Those differ
on any boxed or cropped map, and dividing by n gives a wrong answer of the
right order of magnitude. The nominal value is itself only expected to be
accurate to ±5–15%, which at 1.2 Å is a systematic stretch of every distance in
the model that looks like a slightly strained structure rather than an error.
Anisotropy, cropping and axis permutation are all flagged loudly.
load_map and density_view — contouring honestly
load_map parses the header before touching PyMOL, so a malformed file fails
without leaving a half-loaded object, confirms the object arrived rather than
assuming it, and records provenance — which defaults to unknown and is
never inferred. A measured reconstruction, a sharpened map, a
network-enhanced map and a decoder output are the same isosurface once drawn, so
defaulting to "measured" would assert that somebody observed a generated volume.
density_view draws an isomesh around a selection and states the contour level
in both σ and absolute units. PyMOL normalises maps on load, so its levels
are in σ; EMDB's author-recommended contour is an absolute map value. They are
not interchangeable and the difference is not subtle — EMD-30913 publishes
0.05, which is 3.16 σ; used directly it contours noise.
load_map(path="emd_30913.map.gz", name="emd30913", provenance="measured")
density_view(map_obj="emd30913", selection="chain A", level=0.05, units="absolute")local_resolution_view — where the map is actually good
Colours a map's isosurface by a local-resolution volume instead of by chain. A single global resolution number misrepresents almost every map: a rigid core at 2.5 Å and a flexible periphery at 5 Å live in the same volume.
Two things make this harder than it looks. The volumes must share a voxel grid — colouring one map by another samples it at the first map's coordinates, so a mismatch in extent, spacing, origin or axis order draws colour from the wrong place and renders smooth, plausible and wrong. The tool refuses and names what differs. And because PyMOL normalises on load, ramp breakpoints given in Å are converted to σ against the resolution map's own header — a different σ scale from the contour level, which comes from the density map's. Every breakpoint is reported in both units.
Local resolution is an estimate: estimators disagree with each other on the same map, and the value at a voxel depends on the window and the mask as much as on the data.
local_resolution_view(map_obj="emd30913", res_obj="emd30913_locres",
level=0.05, units="absolute")Ensembles — motion, and what not to claim from it
Four tools for heterogeneity job output, and one result governs all of them. The Flatiron Institute blind challenge put 41 submissions on the same thyroglobulin data: the motions they recovered resembled both each other and the ground truth, but the simulated truth had three population modes, most submissions found two, and only three of 41 found all three. The one they missed was the middle. So: motion is recoverable, populations are not, and these tools draw the first and decline to draw the second.
load_ensemble reads a job directory — cryoDRGN, 3DVA, RECOVAR, 3DFlex,
DynaMight — as ordered frames. They all write the same shape to disk: a
directory of maps plus a table of latent coordinates. Frames are sorted
naturally, so frame 10 does not land between 1 and 2 and silently reorder the
motion. The method is identified from documented markers and never guessed;
an unrecognised directory still loads, and simply stays unidentified.
latent_traverse_view contours those frames into a steppable trajectory. It
refuses when the method was never identified — that is invariant I2, and the
refusal is the point: cryoDRGN's latent density can bear no relation to the
truth while 3DVA's frames are linear interpolations no particle occupied, so
drawing them identically asserts something for one that holds only for the
other. It draws no latent scatter and estimates no density, because the
rendering users most want from latent space is the one the evidence says is most
often wrong.
It also closes a trap specific to trajectories. PyMOL normalises every map independently on load, so contouring each frame at "1.5 σ" contours each at its own σ — and a traversal is exactly the case where density genuinely changes between frames. That is the signal, and per-frame normalisation rescales it away, leaving frames that look reassuringly alike whatever the ensemble does. So the level is held in absolute terms and converted per frame, and the spread of the resulting σ values is reported, because that spread is the change.
deformation_view is the confident one — per-residue displacement between two
states, as colour and as arrows. It refuses states with differing atom counts,
since atoms cannot be paired across them. Where a method estimates deformation
on independent half-sets, pass that table and the arrows are coloured by the
disagreement; without it, every arrow is drawn with identical confidence and
they do not have identical confidence, which the report says out loud.
composition_view is occupancy in sense 2 — the fraction of imaged
particles containing a part, which is a different quantity from the per-atom q
that occupancy_view shows. A model can be q = 1.0 at every atom while the
subunit it belongs to is present in half the particles; both are true and they
answer different questions. So the fractions come from an explicit table and are
never derived from q. The two tools stay separately named forever.
load_ensemble(directory="job042_cryodrgn", name="drgn", method="cryodrgn")
latent_traverse_view(ensemble_name="drgn")
deformation_view(obj_name="1l2y", arrows=True)
composition_view(obj_name="complex", table="chain A=1.0, chain B=0.38")The name
My best friend in high school once shared an apartment with MC Chris, who voiced MC Pee Pants in Aqua Teen Hunger Force. I'm not saying that was the inspiration for the name of this project, but I'm not denying it either.
Provenance
Built on macOS using the open-source PyMOL available via Homebrew. Started with Antigravity, then Gemini Pro 3.1 until I ran out of tokens, then Claude Code (Sonnet 4.6 thinking). Tested with Claude Code and Gemini CLI. Conservation analysis uses the ColabFold public MMseqs2 API (please don't hammer it).
License
MIT.
Available Tools
135 toolsalignCDestructiveIdempotent
Aligns one selection to another
Inputs: mobile (required), target, options. Returns: result
alterCDestructive
Alters atomic properties in a selection
Inputs: selection (required), expression (required). Returns: result
alter_stateCDestructive
Alters atomic coordinates in a state
Inputs: state (required), selection (required), expression (required). Returns: result
altloc_viewAIdempotent
Show every altloc group at once, one colour per group, occupancies labelled.
A multiconformer model says "at this site, these discrete alternatives, in these proportions". PyMOL shows one of them by default, which quietly turns a statement about heterogeneity into a single structure.
Inputs: obj_name (required), label. Returns: result
angleBIdempotent
Measures the angle between three selections and returns it in degrees.
Also draws the measurement as a named angle object.
Inputs: name, selection1, selection2, selection3. Returns: result
asAIdempotent
Shows one representation while hiding all others for the specified selection
Inputs: representation (required), selection. Returns: result
atom_propertiesADestructive
Reads per-atom properties, which nothing else in the tool set can reach.
Object-level facts come back through structure_info and list_chains,
and per-residue values through get_sequence or the view presets. But
properties that live on individual atoms — occupancy, alternate
conformations, per-atom B-factor, formal charge — have no other route: the
PyMOL call that exposes them returns an object that cannot cross the bridge.
Use it to check what you are actually looking at: partial occupancy where a sidechain has two conformations, per-atom pLDDT inside a predicted model, or which atoms carry a formal charge before reasoning about electrostatics.
properties is evaluated by PyMOL once per atom, so it accepts any
expression valid in iterate — the names above are the useful subset.
Inputs: selection (required), max_atoms, properties. Returns: result
backwardB
Goes back one frame
Inputs: no named parameters. Returns: result
bfactor_viewAIdempotent
Colors the structure by crystallographic B-factor (temperature factor).
Blue = rigid/ordered (low B), white = intermediate, red = flexible/disordered (high B). Useful for identifying dynamic loops, disordered termini, and rigid structural cores. Shown as cartoon on black background.
Inputs: obj_name (required). Returns: result
bondCDestructiveIdempotent
Creates a bond between two atoms
Inputs: atom1 (required), atom2 (required), order. Returns: result
cartoonCIdempotent
Sets the cartoon type for the specified selection
Inputs: item_type (required), selection. Returns: result
cdBIdempotent
Changes the current directory
Inputs: path (required). Returns: result
centerBIdempotent
Centers the view on a selection
Inputs: selection. Returns: result
cinematic_viewBIdempotent
Configures PyMOL for a depth-cued, cinematic look with dramatic lighting.
This view emphasizes volume and scale using deep shadows, fog, and depth-cueing. The core of the structure emerges from a dark background, making massive complexes (like ribosomes or viral capsids) look dramatic and imposing. Protein uses standard coloring but with altered material properties.
Inputs: obj_name (required). Returns: result
clipCIdempotent
Adjusts the clipping planes
Inputs: mode (required), distance. Returns: result
colorCIdempotent
Sets the color for a selection.
Inputs: color_name (required), selection. Returns: result
composition_viewAIdempotent
Colour parts of a structure by the fraction of particles containing them.
This is occupancy in SENSE 2 — compositional. A ligand at 40% here means 40% of imaged complexes had it bound. It is not the per-atom crystallographic occupancy q, and it is never derived from q: a model can be q=1.0 at every atom while the subunit it belongs to is present in half the particles. Both statements are true and they answer different questions, so the table must be supplied and this tool never reads an atom property at all. For sense 1, use occupancy_view.
A selection matching no atoms is refused rather than skipped — PyMOL would accept it silently, colour nothing, and leave a render that looks like a fully-present structure.
Inputs: table (required), obj_name (required), label, transparency. Returns: result
conservation_viewAIdempotent
Colors the structure by evolutionary conservation using Shannon entropy.
Runs a full pipeline: extracts the protein sequence from the loaded structure, submits it to an MMseqs2 server (ColabFold public API by default) for multiple sequence alignment, computes per-residue Shannon entropy, and maps the conservation scores onto the structure via the B-factor column and spectrum coloring.
Entropy scores are cached in memory by sequence, so changing the scale or re-running on the same protein does not require a repeat API call.
Magenta/blue = highly conserved (low entropy), white = moderate, cyan/green = highly variable (high entropy).
NOTE: The first call makes an external API call and may take 30 seconds to several minutes depending on the server and sequence length. Subsequent calls for the same sequence are instant.
Inputs: obj_name (required), chain, scale, use_env, +3 more. Returns: result
contact_reportARead-onlyIdempotent
Lists the residues in contact across two selections, with distances and types.
This is the numeric counterpart to ligand_view and interface_view: instead of drawing the interactions, it reports them — which residue pairs touch, how close they get, and whether the contact is a salt bridge, hydrogen bond, hydrophobic packing or pi-stacking. Use it to answer "what holds this ligand in the pocket" or "which residues form this interface".
Classification uses heavy-atom distance criteria, since crystal structures usually have no hydrogens: salt bridge <= 4.0 A between formally charged sidechain tips, hydrogen bond <= 3.5 A between N/O pairs, hydrophobic <= 4.5 A between C/S pairs, pi-stacking <= 5.5 A between aromatic ring centroids (classified parallel or T-shaped by interplanar angle). A reported hydrogen bond is therefore a donor-acceptor pair with plausible geometry, not one verified against a hydrogen position.
Inputs: selection1 (required), selection2 (required), cutoff, max_pairs, +1 more. Returns: result
count_atomsARead-onlyIdempotent
Counts the atoms matching a selection.
Handy for checking a selection expression does what you think before building a scene on top of it — an empty count means the expression is wrong, which is otherwise invisible until the picture comes out blank.
Inputs: selection. Returns: result
createCIdempotent
Creates a new object from a selection
Inputs: name (required), selection, source_state. Returns: result
crosslink_viewBIdempotent
Highlights structural cross-links: disulfide bonds, metals, and their coordination.
Protein backbone shown as a thin grey cartoon. Cysteine side chains (CA→CB→SG) shown as yellow sticks, labeled by residue. Disulfide bonds drawn as yellow dashes. Metal ions shown as orange spheres. Metal coordination bonds drawn as dashed lines to nearby protein atoms. Black background.
Inputs: obj_name (required). Returns: result
deformation_viewAIdempotent
Colour and arrow a model by how far each residue moved between two states.
This is the well-supported tool in the tier. A 41-submission blind challenge found the molecular motions these methods recover resemble both each other and the ground truth; it was relative populations that fell apart. So the arrows mean: density moved this way. They do not mean: this fraction of particles moved this way, and no population can be read out of them.
Refuses when the two states differ in atom count — atoms cannot be paired across them, so a displacement field would be meaningless rather than approximate.
Where a method estimates deformation on independent half-sets, pass that table and the arrows are coloured by the disagreement. Without it every arrow is drawn with identical confidence and they do not have identical confidence, which the report says rather than leaving the picture to imply otherwise.
Inputs: obj_name (required), arrows, as_putty, end_state, +5 more. Returns: result
deleteCDestructiveIdempotent
Deletes objects or selections
Inputs: name (required). Returns: result
density_viewAIdempotent
Draw an isomesh around a selection, stating the contour level in both units.
PyMOL normalises MRC/CCP4 maps on load, so an isomesh level is in sigma. EMDB's author-recommended contour is an absolute map value. They are not interchangeable and the difference is not subtle: EMD-30913 publishes 0.05, which is 3.16 sigma — used directly as a sigma level it contours noise.
So the level is reported in sigma AND absolute units every time, an absolute level is converted before it reaches PyMOL, and EMDB depositions get a pointer to their published contour with the units named. Requires the map to have been loaded through load_map, because the conversion needs the header's mean and RMS.
Inputs: map_obj (required), selection (required), name, carve, +2 more. Returns: result
deselectAIdempotent
Clears the current selection
Inputs: no named parameters. Returns: result
dihedralAIdempotent
Measures the dihedral (torsion) angle between four selections, in degrees.
Also draws the measurement as a named dihedral object. Useful for backbone phi/psi angles and ligand torsions.
Inputs: name, selection1, selection2, selection3, +1 more. Returns: result
distanceAIdempotent
Measures the distance between two selections and returns it in Angstrom.
Also draws the measurement in the viewport as a named distance object. With multi-atom selections PyMOL reports the average over the pairs it found within its default cutoff.
Inputs: name (required), selection1 (required), selection2 (required). Returns: result
drawBIdempotent
Uses OpenGL renderer (faster but lower quality)
Inputs: width, height. Returns: result
electrostatic_viewAIdempotent
Colors the molecular surface by approximate residue-based electrostatics.
Surface is colored red→white→blue via a B-factor spectrum. A white cartoon is shown beneath a semi-transparent surface. Organic ligands shown as sticks with yellow carbons.
For a more accurate Poisson-Boltzmann electrostatic surface, use poisson_boltzmann_view (requires APBS and PDB2PQR to be installed).
Inputs: obj_name (required), mode. Returns: result
ensemble_spread_viewAIdempotent
Colour and thicken a multi-state object by how much its states disagree.
Per-residue RMS deviation across states, pushed into the B-factor column and spectrum-coloured blue (rigid) to red (variable).
Spread is a description of how much the deposited members differ. It is NOT a calibrated uncertainty and NOT an error bar: the number of members and the refinement protocol both shape it, so a wider tube means these models disagree more, not that the true position is less well determined.
Inputs: obj_name (required), as_putty. Returns: result
execute_pymol_commandADestructive
Executes a raw PyMOL command string (PyMOL CLI syntax). PREFER the dedicated tools when one
exists — show, color, select, distance, ligand_view, interface_view, etc. They have better
defaults, do compound setup in one call, and produce cleaner results. Reach for this tool
only when no other tool covers what you need (e.g. set ray_shadow, 0, bg_color grey20, multi-statement scripts). It takes PyMOL's command language, as typed at the
PyMOL prompt. That language includes Python: a line starting with / and a
python ... python end block run as Python inside PyMOL, with full access to the
machine, so treat a command from untrusted text (a file, a web page) accordingly.
Returns once the command has finished, with what PyMOL printed (get_view, iterate
output, ...). If PyMOL rejects a line — a bad selection, a typo, a Python error — the
result is an error naming that line, in PyMOL's words; warnings from lines that still ran
are listed. Put each command on its own line: alter, iterate and label take
the rest of the line literally, so ; does not start a new command after them.
Inputs: command (required). Returns: result
extractCIdempotent
Extracts a selection to a new object
Inputs: name (required), selection. Returns: result
fabC
Creates a peptide chain from a sequence
Inputs: sequence (required), options. Returns: result
fetch_alphafoldADestructiveIdempotent
Fetches a predicted structure from AlphaFold DB by UniProt accession.
These are predictions, not experimental structures, so the model is coloured by pLDDT confidence rather than the usual style — dark blue is reliable, orange is essentially unmodelled. Read the orange and yellow regions as "probably disordered or wrong", not as flexible loops.
Note that pLDDT rides in the B-factor column, so bfactor_view and
putty_view will mis-colour these models (they assume low = rigid,
which is backwards for confidence). Use plddt_view instead.
Inputs: uniprot_id (required), replace, fragment, obj_name, +1 more. Returns: result
fetch_structureADestructiveIdempotent
Fetches a protein structure from the PDB, or a predicted model from AlphaFold DB.
By default, it attempts to fetch the first biological assembly (multimer), and removes any unrelated chains/states that are not part of the primary multimer.
A UniProt accession or an AF- prefixed identifier routes to AlphaFold DB
instead and is coloured by pLDDT confidence — see :func:fetch_alphafold.
Inputs: pdb_code (required), replace, obj_name, multimer_cutoff. Returns: result
forwardB
Advances one frame
Inputs: no named parameters. Returns: result
fragmentC
Loads a molecular fragment
Inputs: name (required). Returns: result
frameCIdempotent
Sets or queries the current frame
Inputs: frame_number. Returns: result
full_screenBIdempotent
Toggles fullscreen mode
Inputs: no named parameters. Returns: result
get_sequenceARead-onlyIdempotent
Returns the amino-acid sequence of a loaded structure, in FASTA.
Also reports how the sequence positions line up with the residue numbers in the file, and where the chain is broken. Both matter: PDB numbering rarely starts at 1, so "residue 50" in a paper and position 50 in the sequence are usually different residues — and unmodelled loops leave gaps in the structure that the sequence alone does not reveal.
Inputs: obj_name (required), chain. Returns: result
h_addCDestructiveIdempotent
Adds hydrogens to a selection
Inputs: selection. Returns: result
helpCRead-onlyIdempotent
Shows help for a command
Inputs: command. Returns: result
h_fillADestructiveIdempotent
Fills open valences on the currently picked atom with hydrogens.
Takes no selection: cmd.h_fill operates on PyMOL's editor pick, so it needs
an atom picked in the GUI and cannot be aimed from here. Passing it a
selection used to land the string in its quiet argument and fail with an
integer conversion error. For adding hydrogens to a selection over the
bridge, use h_add.
Inputs: no named parameters. Returns: result
hideBIdempotent
Hides a graphical representation for a given selection.
Inputs: representation (required), selection. Returns: result
hydrophobic_surface_viewBIdempotent
Colors the molecular surface by amino acid hydrophobicity.
Orange = hydrophobic (ILE, VAL, LEU, PHE, MET, ALA, TRP, PRO), white = polar (SER, THR, CYS, TYR, ASN, GLN, GLY), sky blue = positively charged (ARG, LYS, HIS), salmon = negatively charged (ASP, GLU). A white cartoon is shown beneath a semi-transparent surface. Organic ligands shown as sticks with yellow carbons.
Inputs: obj_name (required). Returns: result
interface_reportAIdempotent
Measures how large a protein-protein interface is, and which residues form it.
Reports buried surface area — the standard measure of how much of a complex is actually complex — by comparing each chain's solvent-accessible area free and bound. Also ranks the residues by how much surface each buries, and breaks the interface down by residue chemistry.
Interpretation: a per-side area under ~400 A^2 is usually a crystal packing contact rather than a biological interface, while over ~1000 A^2 indicates a substantial, likely specific association. These are guides from PDB-wide surveys, not a verdict — small biological interfaces exist.
For the interactions themselves — which pairs hydrogen bond, which form
salt bridges — use contact_report on the same two chains.
Inputs: chain_a (required), chain_b (required), obj_name (required), max_residues. Returns: result
interface_viewAIdempotent
Highlights the protein-protein binding interface between two chains.
Chain A shown in marine blue, chain B in salmon. Interface residues (within 4Å of the partner chain) shown as a solid surface patch with sticks. H-bonds across the interface drawn as yellow dashes.
Inputs: chain_a (required), chain_b (required), obj_name (required). Returns: result
intra_fitBDestructiveIdempotent
Fits all states within an object
Inputs: selection (required). Returns: result
intra_rmsBRead-onlyIdempotent
Calculates RMSD between states within an object
Inputs: selection (required). Returns: result
isomeshCIdempotent
Creates a mesh isosurface
Inputs: name (required), level (required), map_object (required), selection. Returns: result
isosurfaceCIdempotent
Creates a solid isosurface
Inputs: name (required), level (required), map_object (required), selection. Returns: result
labelCIdempotent
Adds labels to atoms in the selection
Inputs: selection (required), expression. Returns: result
latent_traverse_viewAIdempotent
Step through an ensemble's conformations as a contoured trajectory.
Refuses when the generating method was never identified. That is SPEC invariant I2 working, not a failure: cryoDRGN's latent density can bear no relation to the truth while 3DVA's frames are linear interpolations no particle occupied, and rendering both the same way asserts something for one that holds only for the other.
The contour is held at a constant ABSOLUTE value and converted to each frame's own sigma. PyMOL normalises every map independently on load, so a fixed sigma level would contour each frame at its own scale and flatten away the density change the traversal exists to show.
No latent scatter and no density estimate are drawn, deliberately. In a 41-submission blind challenge most methods missed a genuinely present middle state, so an empty region of latent space is a region of unknown occupancy — never evidence that a conformation does not occur.
Inputs: ensemble_name (required), name, color, level, +2 more. Returns: result
ligand_viewAIdempotent
Shows a binding-site view focused on a ligand.
Protein rendered as a semi-transparent cartoon. Pocket residues (within 5Å of the ligand) shown as sticks with element coloring and lightblue carbons. Ligand shown as thick sticks with yellow carbons. H-bonds drawn as yellow dashes. Pocket residues labeled. View zooms to the ligand.
Inputs: obj_name (required), ligand_resn (required). Returns: result
list_chainsARead-onlyIdempotent
Lists the chain IDs present in an object (or in all objects).
Useful before calling :func:interface_view, :func:conservation_view
or any tool that needs a specific chain ID.
Inputs: obj_name. Returns: result
list_ligandsARead-onlyIdempotent
Lists the small-molecule (organic) ligand residue names in an object.
Call this before :func:ligand_view, :func:pocket_view, or
:func:pharmacophore_view when you don't already know the ligand's
residue name (three characters, or five for newer CCD codes).
Inputs: obj_name (required). Returns: result
list_objectsARead-onlyIdempotent
Lists all loaded PyMOL objects.
Call this when you don't know what's currently in the session — for
example before composing a selection or running a view tool that needs
an obj_name.
Inputs: no named parameters. Returns: result
load_ensembleADestructiveIdempotent
Load a cryo-EM heterogeneity job's volumes in trajectory order.
Every method in this space writes the same thing: a directory of maps plus a table of latent coordinates. This reads them in trajectory order — naturally, so frame 10 does not sort between 1 and 2 and silently reorder the motion.
The generating method is identified from documented on-disk markers and is never guessed. A directory that matches nothing loads its volumes fine and stays unidentified, which makes latent views refuse to render: an unlabelled latent plot is what SPEC invariant I2 forbids, because each method's caveat is different and they are not interchangeable. Pass method= if you know.
Provenance defaults to "generated" rather than "unknown" — nothing observed a decoder's output — and the report says it declared that and on what evidence.
Inputs: directory (required), name, method, provenance, +2 more. Returns: result
load_mapADestructiveIdempotent
Load a volume into PyMOL, recording where it came from and reporting its geometry.
The header is parsed before PyMOL is touched, so a malformed file fails without leaving a half-loaded object in the session, and the load is confirmed rather than assumed.
Provenance defaults to unknown and is never guessed. A measured reconstruction, a sharpened map, a network-enhanced map and a decoder output all render identically once they are an isosurface, so defaulting to "measured" would quietly assert that somebody observed a generated volume. The report shows what the file says about itself — MRC labels, filename tokens — so the caller can declare it.
Inputs: path (required), name, provenance. Returns: result
load_sessionADestructiveIdempotent
Restores a PyMOL session from a .pse file.
By default this replaces everything currently loaded, exactly as opening
the file in PyMOL would. Set merge=True to add its objects to the
current session instead, which is how you get two saved scenes side by
side — though note that objects with the same name will collide.
Inputs: filename (required), merge. Returns: result
load_structureADestructiveIdempotent
Loads a structure from a local file path and applies the BFS multimer heuristic.
Inputs: obj_name (required), file_path (required), replace, multimer_cutoff. Returns: result
local_resolution_viewAIdempotent
Colour a map's isosurface by a local-resolution volume instead of by chain.
A single global resolution number misrepresents almost every map: a rigid core at 2.5 Å and a flexible periphery at 5 Å live in the same volume, and one isosurface invites the reader to believe all of it is equally real.
Two things make this harder than it looks, and both are handled. The volumes must share a voxel grid — colouring one map by another samples it at the first map's coordinates, so a mismatch in extent, spacing, origin or axis order draws colour from the wrong place and renders smooth, plausible and wrong. This tool refuses and names what differs. And PyMOL normalises maps on load, so ramp breakpoints given in Ångström must be converted to sigma against the RESOLUTION map's own header — a different sigma scale from the contour level, which comes from the density map's. Every breakpoint is reported in both units.
Local resolution is an estimate. Estimators disagree with each other on the same map, and the value at a voxel depends on the window and the mask as much as on the data.
Inputs: map_obj (required), res_obj (required), name, carve, +7 more. Returns: result
lsCRead-onlyIdempotent
Lists files in the current directory
Inputs: path. Returns: result
map_infoARead-onlyIdempotent
Report an MRC/CCP4 map's geometry, above all its voxel size.
Reads only the 1024-byte header — the map data is never loaded, PyMOL is never touched, and nothing goes over the network.
Voxel size is not stored in the header, it is derived, and the derivation has a trap: it is cella/m (the grid sampling), not cella/n (the stored extent). Those differ on any boxed or cropped map, and dividing by n gives a wrong answer of the right order of magnitude. The nominal value is only expected to be accurate to ±5–15% in the first place, which at 1.2 Å is a systematic stretch of every distance in the model. Anisotropy, cropping and axis permutation are all flagged loudly.
Inputs: path (required). Returns: result
morph_statesADestructiveIdempotent
Interpolate between states, refusing when interpolation is ill-posed.
The value here is the refusal, not the interpolation — PyMOL morphs natively. A morph is only meaningful when every state shares a topology, so that atom i in state 1 is the same atom as atom i in state 2. That holds for a deformation-model ensemble (3DFlex, DynaMight). It does not hold for volumes reconstructed and modelled independently, and a morph across those animates a correspondence nobody established.
Note that cmd.morph is Incentive-only. On open-source PyMOL the topology check still runs and reports; only the interpolation is unavailable.
Inputs: obj_name (required), name, steps, validate_only. Returns: result
moveBDestructive
Moves the camera along an axis
Inputs: axis (required), distance. Returns: result
mplayBIdempotent
Starts playing the movie
Inputs: no named parameters. Returns: result
mpngBDestructiveIdempotent
Saves a series of PNG images for movie frames
Inputs: prefix (required). Returns: result
msetCIdempotent
Defines a sequence of states for movie playback
Inputs: specification (required). Returns: result
mstopBIdempotent
Stops the movie
Inputs: no named parameters. Returns: result
mutation_viewAIdempotent
Highlights mutated residues on the protein structure.
Given a comma-separated list of mutations in standard notation (e.g. "A123G,V45L,T200S"), the mutated residues are shown as magenta sticks and labeled. Nearby residues (within 4 Å) are shown as thin grey sticks for packing context. The protein backbone is shown as a grey cartoon. Organic ligands are shown as yellow sticks.
Mutation format: <wildtype_aa><mutant_aa>, e.g. "A123G" (Ala→Gly at position 123). Chain can optionally be prefixed: "A:A123G".
Inputs: obj_name (required), mutations (required). Returns: result
occupancy_viewAIdempotent
Colour and scale a structure by per-atom crystallographic occupancy (q).
Alternates at q<1 are visually de-emphasised in proportion, so a half-occupied conformer looks half-there instead of looking like a confident model.
This is occupancy in the crystallographic sense — the fraction of unit cells in which an atom sits at this position. It is NOT the fraction of imaged particles containing a subunit; a model can be q=1.0 everywhere while the subunit is present in half the particles. Both are true and they are different questions, so this tool never reports the other sense.
Inputs: obj_name (required), preserve_bfactors. Returns: result
orientCIdempotent
Orients the view to align with principal axes of the selection
Inputs: selection. Returns: result
pharmacophore_viewAIdempotent
Colors a ligand by pharmacophore feature type.
The ligand is shown as sticks color-coded by pharmacophore property: violet=ring/aromatic carbon, yellow=aliphatic carbon, skyblue=nitrogen (H-bond donor/acceptor), salmon=oxygen (H-bond acceptor), gold=sulfur, palegreen=halogen (F/Cl/Br/I). H-bonds to protein are shown as cyan dashes. Interacting residue sidechains are shown as element-colored sticks with CA labels. The pocket is shown as a semi-transparent grey surface for cavity context. The protein backbone is shown as a thin grey cartoon.
Inputs: resn (required), obj_name (required). Returns: result
plddt_viewAIdempotent
Colors an AlphaFold model by pLDDT confidence, using the official palette.
Dark blue = very high (>90), light blue = confident (70-90), yellow = low (50-70), orange = very low (<50). Regions below 70 are usually intrinsically disordered or simply unreliable — read them as "the model does not know", not as a flexible loop.
AlphaFold stores pLDDT in the B-factor column, which is why bfactor_view
and putty_view get these models backwards: they assume low = rigid,
whereas low pLDDT = low confidence. Use this instead for predicted models.
Inputs: obj_name (required). Returns: result
pngCDestructiveIdempotent
Saves a PNG image
Inputs: filename (required), options. Returns: result
pocket_viewAIdempotent
Visualizes the binding pocket cavity around a ligand as a colored surface.
The pocket (all residues within 5 Å of the ligand) is shown as a semi-transparent surface colored by chemical character: orange=hydrophobic, white=polar, skyblue=positive, salmon=negative. Pocket residue sidechains are shown as sticks. The ligand is shown as yellow sticks. H-bonds between the ligand and pocket are drawn as cyan dashes. The protein backbone is shown as a thin grey cartoon for context.
Inputs: resn (required), obj_name (required). Returns: result
pointillist_viewAIdempotent
Renders the structure as an artistic, abstract pointillist/starfield cloud.
The continuous surface is replaced by thousands of individual dots representing the solvent-accessible surface, resembling a galaxy or pointillist painting. The protein backbone is hidden to emphasize the scattered volume. Ligands are shown as bright yellow spheres (stars) embedded in the cloud.
Inputs: obj_name (required). Returns: result
poisson_boltzmann_viewAIdempotent
Colors the molecular surface by true Poisson-Boltzmann electrostatic potential.
Runs PDB2PQR (AMBER force field, pH 7.0) then APBS to compute the full electrostatic potential map. Surface is colored red→white→blue over the range ±20 kT/e. A white cartoon is shown beneath a semi-transparent surface. Organic ligands shown as sticks with yellow carbons.
Requires APBS and PDB2PQR to be installed on the system: brew install brewsci/bio/apbs pip install pdb2pqr
Inputs: obj_name (required). Returns: result
print_exportADestructiveIdempotent
Exports a structure as watertight STL files ready for multi-colour 3D printing.
Each colour group becomes one STL file. PyMOL's exporters write the whole visible scene, so each group is isolated on its own before export, then rebuilt into a watertight solid. Every STL is written in PyMOL model coordinates (Å, the numbers get_coords reports) whatever the camera view, so groups from one call, or from separate calls, line up; the camera is left as it was. A slicer can load them as aligned multi-material parts (e.g. add the second STL as a "part" of the first in Bambu Studio).
representation="displayed" prints what PyMOL shows, sticks and spheres included; "cartoon" keeps to cartoon and surface triangles and names what it left out. A group keeps every separate piece (two chains that do not touch print as two pieces) unless bodies="largest". The voxel method's growth of about 0.62 voxel per surface is undone unless undo_voxel_growth=False, but gaps narrower than about 2.5 voxels fuse while voxelising and cannot be reopened: a clearance needs voxel_pitch <= gap / 2.5.
STL has no units and slicers read it as millimetres, so mm_per_angstrom
sets the print size. The result gives each part's size in mm and warns about
any part small enough for a slicer to take for inches and enlarge 25.4x.
Requires the optional print extra (trimesh, pymeshlab, manifold3d); see
the install hint returned if the libraries are missing.
Inputs: groups (required), obj_name (required), bodies, method, +6 more. Returns: result
print_ribbon_viewAIdempotent
Chunky β-arrow ribbons plus a continuous backbone "spine", tuned for rigid, gap-free 3D printing.
Configures the look developed for FDM printing: thick β-strand arrows
and a fat helix on the main object with loop cartoon hidden, plus a
separate <obj>_spine object showing PyMOL's cartoon tube (which
ignores secondary structure) running unbroken through the whole
backbone. The spine threads through the strand bodies, so when the two
objects are exported together the voxel step fuses them into one
watertight solid with no strand→loop discontinuity. The spine also acts
as internal rebar, reinforcing the thin junctions for print rigidity.
The style is set on the object and its spine only; other objects and PyMOL's global settings are left alone. The spine is carried through residues with no CA atom, such as GFP's chromophore, without renaming anything.
PyMOL draws a strand √2 times the strand_width and strand_thickness
settings, so the defaults (2.8, 2.0) give strands about 4.0 x 2.8 Å, and
a β-barrel's wall closes up. To see into a barrel, use
strand_width=2.0, strand_thickness=1.0, spine_in_strands=False.
Measured on GFP (2b3p): the see-through share of the barrel wall goes
from 8% to 29%; thinner strands alone leave 399 ų of spine bulging out
of them, which spine_in_strands=False takes to 1 ų; and it still
exports as one solid (unbridged at the chromophore, it split 69:31).
After calling this, export the fused solid with::
print_export(obj_name="<obj>",
groups="<obj>=(<obj> or <obj>_spine)",
representation="cartoon",
method="voxel", voxel_pitch=0.2)
Inputs: obj_name (required), spine_radius, strand_width, strand_overlap, +3 more. Returns: result
putty_viewAIdempotent
Visualizes protein flexibility using a putty (tube-width) representation.
The cartoon tube radius scales linearly with crystallographic B-factor: thin/blue = rigid/ordered regions, thick/red = flexible/disordered regions. A 70%-transparent surface is shown, also colored by B-factor. Organic ligands are shown as sticks with yellow carbons. Black background.
Inputs: obj_name (required). Returns: result
pwdARead-onlyIdempotent
Prints the current directory
Inputs: no named parameters. Returns: result
qscore_viewAIdempotent
Colour a model by per-residue Q-score parsed from its wwPDB validation report.
No network, no map, and no computation — Q-scores are already published, and this reads the numbers rather than re-deriving them.
Two things to expect from real data: entries deposited before the September 2023 validation rollout carry no Q-scores at all, which is the common case for older EM structures; and real Q-scores go negative, so the published 0–1 framing is the intended range and not the observed one.
Inputs: obj_name (required), validation_path (required), preserve_bfactors. Returns: result
rayCIdempotent
Performs ray-tracing
Inputs: width, height. Returns: result
rebuildCIdempotent
Regenerates all displayed geometry
Inputs: selection. Returns: result
refreshCIdempotent
Refreshes the display
Inputs: no named parameters. Returns: result
removeADestructiveIdempotent
Permanently removes the atoms matching the selection. This deletes atoms; it does not just
hide them. To hide instead, use :func:hide.
Inputs: selection (required). Returns: result
renderADestructiveIdempotent
Renders the current scene and returns the image, so you can see it.
Use this instead of calling ray and png separately — those leave
you holding a filename you cannot look at. Call this after setting up a
view to check what it actually looks like, and iterate.
Every render is ray-traced, which takes seconds to minutes on a large
assembly. ray_trace=False is accepted but ignored: PyMOL's fast
unshaded frame grab needs its GUI thread, which this plugin does not run
on, so that path wrote blank images. Render smaller to render faster.
Inputs: width, height, filename, ray_trace.
resetCDestructiveIdempotent
Resets the view, optionally resetting an object's matrix
Inputs: obj. Returns: result
restore_bfactorsADestructiveIdempotent
Restore the B-factors a Wiggles view overwrote.
occupancy_view, ensemble_spread_view and qscore_view all push their values into the B-factor column so PyMOL can spectrum-colour by them. The originals are stashed first; this puts them back in one pass.
Inputs: obj_name (required). Returns: result
rms_curARead-onlyIdempotent
Measures RMSD between two selections without moving anything.
Use this when the structures are already superposed, or when you want to
know how far apart they are as currently positioned. Compare with align
and super, which move the mobile structure to minimise RMSD before
reporting it, and with superposition_view, which shows where the
difference is rather than summarising it as one number.
Requires the two selections to have matching atom counts.
Inputs: mobile (required), target (required). Returns: result
rockCIdempotent
Toggles a rocking animation
Inputs: no named parameters. Returns: result
sasaARead-onlyIdempotent
Measures solvent-accessible surface area, in square Angstrom.
Reports the SASA of selection in the context of the object it belongs
to — so a chain measured inside a complex is already partly occluded by
its partner. To get the free (unbound) area, copy the chain to its own
object first with create, or use interface_report, which does the
bound/free bookkeeping for you.
Accuracy depends on PyMOL's dot_solvent (0 = molecular surface,
1 = solvent-accessible) and dot_density settings.
Inputs: state, selection. Returns: result
saveCDestructiveIdempotent
Saves data to a file
Inputs: filename (required), state, selection. Returns: result
save_sessionADestructiveIdempotent
Saves the entire PyMOL session to a .pse file.
A session captures everything — every object, selection, representation, colour, scene and the camera — so the work can be reopened exactly as it was. Use this before experimenting with a scene you would not want to rebuild, and to hand a finished figure to a colleague.
Unlike save, which writes bare coordinates, this preserves the whole
visual state.
Inputs: filename (required). Returns: result
sceneCIdempotent
Manages scenes for later recall
Inputs: key (required), action. Returns: result
scene_orderCIdempotent
Sets the order of scenes
Inputs: scene_list (required). Returns: result
sculpt_activateCIdempotent
Activates sculpting mode for an object
Inputs: obj (required). Returns: result
sculpt_deactivateBIdempotent
Deactivates sculpting mode for an object
Inputs: obj (required). Returns: result
sculpt_iterateCDestructive
Performs sculpting iterations
Inputs: obj (required), state, iterations. Returns: result
selectAIdempotent
Creates (or replaces) a named selection for later reuse.
Inputs: name (required), selection (required). Returns: result
setAIdempotent
Sets a PyMOL setting to a specified value.
Settings live at a level — global, object, object-state, atom or bond — and PyMOL ignores a
value stored below its setting's level. cartoon_tube_radius on a residue range is
stored per atom and never drawn; ray_shadow on an object is never read. PyMOL only
warns about that, so this reports it as an error, with what to do instead.
Inputs: value (required), setting (required), selection. Returns: result
set_symmetryCDestructiveIdempotent
Sets symmetry parameters for an object
Inputs: a (required), b (required), c (required), beta (required), +3 more. Returns: result
showCIdempotent
Shows a graphical representation for a given selection.
Inputs: representation (required), selection. Returns: result
spectrumCIdempotent
Colors selection in a spectrum
Inputs: expression (required), palette, selection. Returns: result
spheroidCIdempotent
Displays atoms as smooth spheres
Inputs: obj. Returns: result
structure_infoARead-onlyIdempotent
Summarises what a loaded structure actually is, in one call.
Answers the question you ask before any analysis: what protein is this, how was it determined, at what resolution, what is in the file. Combines what PyMOL knows (chains, residue and atom counts, ligands, symmetry) with entry metadata from the RCSB (title, method, resolution, release date, source organism).
Metadata lookup is best-effort — it is skipped silently if the object is not named after a PDB entry, or the API is unreachable.
Inputs: obj_name (required), pdb_id. Returns: result
superCDestructiveIdempotent
Superimposes one selection onto another
Inputs: mobile (required), target, options. Returns: result
superposition_viewAIdempotent
Superposes two structures and colors the mobile one by per-residue shift.
An RMSD alone tells you that something moved, not where. This superposes
mobile onto target, measures how far each residue's CA ended up
from its counterpart, and colors the mobile structure blue (unchanged)
through white to red (most shifted). The target is left as a grey
reference cartoon.
Best on two states of the same protein — apo vs holo, open vs closed, a mutant against wild type. Residues are paired by chain and residue number, falling back to residue number alone when the two use different chain IDs.
Both structures have to be loaded first, and fetch_structure clears the
session by default — so fetch the second one with replace=False or it
will replace the first. If either entry is a multimer, compare single
chains (create one object per chain): superposing one dimer onto
another fits the assembly rather than the fold, which inflates the RMSD
dramatically. 4AKE against 1AKE gives 18.5 A as deposited dimers and
2.1 A chain-to-chain.
Inputs: mobile (required), target (required), method, max_deviation. Returns: result
symexpC
Generates symmetry-related copies
Inputs: prefix (required), obj_name (required), selection (required), segi, +1 more. Returns: result
systemCDestructive
Executes a system command
Inputs: command (required). Returns: result
textbook_viewAIdempotent
Configures PyMOL for a crisp, cel-shaded illustrative look ("Textbook Illustration").
This view transforms the structure into a bold, 2D illustrative style with sharp black outlines, ideal for presentations or textbook-style diagrams. It hides the interior complexities, showing a solid white cartoon and surface with heavy black edge contours. Ligands are styled similarly as opaque white sticks with outlines.
Inputs: obj_name (required). Returns: result
turnB
Rotates the camera around an axis
Inputs: axis (required), angle. Returns: result
turntableADestructiveIdempotent
Renders a full 360° rotation as a numbered PNG sequence.
Spins the camera around the vertical axis in equal steps and writes one
frame per step, ready to assemble into a GIF or MP4 (e.g.
ffmpeg -i turntable_0000.png out.mp4).
Every frame is ray-traced, which is slow — 36 frames of a large assembly can take an hour, so start with few frames and a small width/height. The unshaded OpenGL renderer would be far faster but does not work over this bridge (it needs PyMOL's GUI thread), and silently produced blank frames until this was found.
Inputs: width, frames, height, prefix, +3 more. Returns: result
unbondBDestructiveIdempotent
Removes a bond between two atoms
Inputs: atom1 (required), atom2 (required). Returns: result
util_cbabCIdempotent
Colors by atom, slate carbons (Color By Atom, slateBLue)
Inputs: selection. Returns: result
util_cbacCIdempotent
Colors by atom, cyan carbons (Color By Atom, Cyan)
Inputs: selection. Returns: result
util_cbagCIdempotent
Colors by atom, green carbons (Color By Atom, Green)
Inputs: selection. Returns: result
util_cbakCIdempotent
Colors by atom, pink carbons (Color By Atom, pinK)
Inputs: selection. Returns: result
util_cbamCIdempotent
Colors by atom, magenta carbons (Color By Atom, Magenta)
Inputs: selection. Returns: result
util_cbaoBIdempotent
Colors by atom, orange carbons (Color By Atom, Orange)
Inputs: selection. Returns: result
util_cbapBIdempotent
Colors by atom, purple carbons (Color By Atom, Purple)
Inputs: selection. Returns: result
util_cbasCIdempotent
Colors by atom, salmon carbons (Color By Atom, Salmon)
Inputs: selection. Returns: result
util_cbawCIdempotent
Colors by atom, white carbons (Color By Atom, White)
Inputs: selection. Returns: result
util_cbayBIdempotent
Colors by atom, yellow carbons (Color By Atom, Yellow)
Inputs: selection. Returns: result
util_cbcCIdempotent
Colors by chain (Color By Chain)
Inputs: selection. Returns: result
util_chainbowCIdempotent
Colors chains in rainbow gradient (CHAINs in rainBOW)
Inputs: selection. Returns: result
util_color_by_elementCIdempotent
Colors atoms by their element
Inputs: selection. Returns: result
util_color_secondaryCIdempotent
Colors secondary structure elements
Inputs: selection. Returns: result
util_rainbowCIdempotent
Colors residues in rainbow from N to C terminus
Inputs: selection. Returns: result
util_ssCIdempotent
Colors by secondary structure
Inputs: selection. Returns: result
viewportCIdempotent
Sets the viewport size
Inputs: width (required), height (required). Returns: result
zoomCIdempotent
Zooms the view on a selection
Inputs: buffer, selection. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 135 tools
There are several near-duplicate clusters: ten `util_cb*` tools all do "color by atom with a different carbon color," and `util_rainbow`/`util_chainbow`/`util_ss`/`util_color_by_element`/`util_color_secondary`/`spectrum`/`color` all recolor structures. Rendering/export tools (`ray`, `render`, `draw`, `png`, `mpng`, `turntable`, `print_export`, `print_ribbon_view`) and representation tools (`show`, `as`, `spheroid`, `isomesh`, `isosurface`, `cartoon`) overlap enough that an agent must read long descriptions to choose. Individual descriptions are excellent and often explicitly cross-reference siblings, which rescues some but not all of the boundaries.
At least four conventions coexist: bare PyMOL command names (`as`, `set`, `show`, `hide`, `color`, `turn`, `scene`, `frame`, `clip`), an `util_` prefix group with ad-hoc suffixes (`util_cbam`, `util_cbak`, `util_cbc`, `util_chainbow`), a `_view` suffix group (`ligand_view`, `putty_view`, `qscore_view`), and a `*_report`/`*_info` group. Several names are single vague words (`as`, `set`, `do`-like `draw`, `fab`, `mset`, `mpng`) that give no hint of scope.
135 tools is an order of magnitude beyond what an agent can hold in context for a single server, and many are trivially redundant (ten carbon-color variants, three isosurface/mesh tools, four render paths). The surface should be compressed into parameterized tools (e.g. one `color_by_atom(carbon=...)`, one `render(kind=...)`).
The domain (scripting PyMOL) is covered practically end to end: loading/session, selections, representations, measurements, analysis reports, views/presets, movies, scenes, ray-tracing, and 3D-print export. `execute_pymol_command` provides an explicit escape hatch for whatever the curated set misses. Minor gaps (e.g. no dedicated undo/history, some settings only reachable via `set`/`execute_pymol_command`) are workable.
Maintenance
Related MCP Connectors
Agent-to-Agent (A2A) + Model Context Protocol (MCP) hub for peptides.
AI-powered bioprotocol optimization — generate, search, and manage lab protocols via MCP
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Protein analysis: ESM-2/ESMC embeddings, mutation scoring, landscape scans, ESMFold structure.
Related MCP Servers
- AlicenseBqualityDmaintenanceA Model Context Protocol server that enhances language models with protein structure analysis capabilities, enabling detailed active site analysis and disease-related protein searches through established protein databases.220ISC
- AlicenseBqualityDmaintenanceA comprehensive Model Context Protocol server that enables advanced PubMed literature search, citation formatting, and research analysis through natural language interactions.1210MIT
- AlicenseNot gradedqualityFmaintenanceA Model Context Protocol server that enables AI assistants to interact with LAMMPS for molecular dynamics simulations through natural language commands.13Apache 2.0
- AlicenseNot gradedqualityBmaintenanceA Model Context Protocol server providing programmatic access to 3D protein structural data from RCSB PDB, PDBe, and UniProt, enabling search, retrieval, comparison, and analysis of protein structures.466 npm6Apache 2.0